Realm-cocoa: Realm async writes really works

Created on 2 Feb 2017  Â·  9Comments  Â·  Source: realm/realm-cocoa

I have created a singleton class having following method to write but it crashes at times because of incorrect thread access:

func save<T:Object>(_ realmObject:T) {
    let backgroundQueue = DispatchQueue(label: ".realm", qos: .background)
    backgroundQueue.async {
        let realm = try! Realm()
        try! realm.write {
            realm.add(realmObject)
        }
    }    
}

I am getting crash always.

T-Help

Most helpful comment

The Realm property is nil for unmanaged objects.

All 9 comments

Hi @santhoshs5. Would you be able to provide us with a code snippet of where you call func save<T:Object>(_ realmObject:T) as well as the stack trace for the crash. I'm looking forward to seeing this as we'll be able to better assist you.

@santhoshs5, in your code snippet you're passing an object across threads. Realm objects can only be access on the thread on which they were created. See the documentation's section on passing instances across threads for more information.

@bdash I considered your input and changed the method to following.
Now I am getting this exception:

'RLMException', reason: 'Cannot construct reference to unmanaged object, which can be passed across threads directly'
func save<T:Object>(_ realmObject:T) {
    let objectRef = ThreadSafeReference(to: realmObject)
    let backgroundQueue = DispatchQueue(label: ".realm", qos: .background)
    backgroundQueue.async {
        let realm = try! Realm()
        guard let realmObject = realm.resolve(objectRef) else {
            return // person was deleted
        }

        try! realm.write {
            realm.add(realmObject)
        }
    }   
}

@istx25

I am calling this method as following.

RealmHelper.shared().save(userInfo!)

Here userInfo object realm object.

As the exception says, unmanaged objects (i.e., objects not associated with a Realm) should be passed directly rather than via a thread safe reference. The fact you're hitting both exceptions from the same code suggests you're passing both unmanaged and managed objects, so you'll need to accommodate that.

@bdash

I do get that to clear the confusion managed object means Realm objects which are derived from Object.

is it good practice to have singleton to manage realm.

Could you explain me more from my code what's wrong. as i am newbie to realm.

One more thing I am using this method for reading from realm.

func fetch<T:Object>(type:T.Type,predicate:NSPredicate?) throws -> Results<T>{
    let results:Results<T>!
    do {
         let realm = try Realm()
         if let predicate = predicate {
             results = realm.objects(T.self).filter(predicate)
         } else {
             results = realm.objects(T.self)
         }
    } catch let error {
            throw error
    }
    return results
}

I am using this method as following

let results = try RealmHelper.shared().fetch(type: UserInfo.self, predicate: nil)

setting the results to another variable present in singleton , I am getting crash when i read the object from another thread. What could be the reason

managed object means Realm objects which are derived from Object.

This is not correct.

If you create an object from scratch (for example, let myObject = SomeObject()), that object starts out as unmanaged. You can pass it between threads like any normal object.

Once you add that object to a Realm, it becomes managed. You _can't pass it between threads anymore_ without using the thread safe reference API. If you retrieve an object from a Realm, that object also starts out managed.

Please read our documentation for more information about using Realms in an application with multiple threads or queues.

I have the same problem. How can I check if an RealmObject is managed or unmanaged Object?

The Realm property is nil for unmanaged objects.

Was this page helpful?
0 / 5 - 0 ratings