0

I'm using RealmSwift with AsyncDisplayKit, I'm getting this error all the time from ASDataController.mm:

libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.  

I have a DataSourceManager class that contains the data, and a DatabaseManager that handles the fetch and insert operations.

Exception always occurs in _layoutNodesFromContexts:ofKind:completion:. I've tried any combination of GCD that I knew (Serial, Concurrent, Barrier), but I couldn't handle this exception.

How should I manage this situation?

Thanks!

Alireza
  • 193
  • 2
  • 9

3 Answers3

0

I've tried Unmanaged_RLMObject as workaround. Unmanaged_RLMObject is the RLMObject haven't add to RLMRealm.

It works, but I don't think it's good solution.

Unmanaged instances of RLMObjects behave exactly as regular NSObject subclasses, and are safe to pass across threads.

Source

NSNoob
  • 5,548
  • 6
  • 41
  • 54
0

This is probably because AsyncDisplayKit (or Texture now) works on multiple background threads, and your realm objects are being passed around between threads. That's why the IncorrectThreadException.

To pass your realm objects between threads, use the ThreadSafeReference, along with using realm.resolve where you access your objects in AsyncDisplayKit.

More info here.

Siddharth Gupta
  • 897
  • 5
  • 20
0

The quick and easy solution I have found is instead of accessing your data Model direct in they layoutSpecThatFits methods which are called in the background simply declare a parameter needed from the model and set it in your init method. Then use it in layoutSpecThatFits as usual.

For example:

Assume your data model is Person

class Person: Object {
@objc dynamic var name: String = ""
@objc dynamic var birthday: Date = Date()
}

In your node (CellNode, DisplayNode etc) on layoutSpecThatFit method don't access person direct instead have a property say name which you set it in init method, then use it like so: -

var name: String

init(person: Person){
// Set the property here so that you don't have to call person.name in layoutSpect method.
self.name = person.name 
super.init()
}

override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {

// Now you can safely use the param here on a different thread without issues.
if (self.name) {
// ---
}

}

Reference: I found the idea from this article

Mussa Charles
  • 4,014
  • 2
  • 29
  • 24