Search code examples
swiftrealmsingleton

Global Realm Object: Singleton or Fetch It Every Time?


In my app I need to have global access to a currentUser which is an instance of a User class defined like this:

class User: Object{
  @objc dynamic var recordName = UUID().uuidString
  @objc dynamic var name = ""
  @objc dynamic var email = ""
  @objc dynamic var photo: Data? = nil

  override static func primaryKey() -> String? {
    return "recordName"
  }
}

The currentUser is established when the app launches, and I refer to it frequently almost everywhere in my app.

I've noticed that from time-to-time, I get an error that appears to be caused by referencing this currentUser in different places:

Realm accessed from incorrect thread

I'm able to keep track of which thread Realm is on most of the time, but it's difficult to cover all cases. So this leads me to my question.

Is there a safe way to set the currentUser object once as a singleton? Or should I save their ID to disk and then fetch the object from Realm every time I need it (something like below)?

let realm = try! Realm()
if let currentUserId = defaults.string(forKey: "currentUserId"), let user = realm.object(ofType: User.self, forPrimaryKey: currentUserId){
  currentUser = user
}

I am using Swift 4.2 on Xcode 10. Thanks!


Solution

  • As long as you can make sure that you always access your currentUser object from the same thread, it's fine to set it up as a globally accessible object once and use that auto-updating reference to it instead of re-fetching it every time from Realm.

    You can achieve this by either creating a dedicated thread to Realm and always dispatching to that thread before accessing Realm/currentUser or simply doing it from a system thread, such as DispatchQueue.main.