Область в AsyncDisplayKit вызывает завершение - realm::IncorrectThreadException

Я использую RealmSwift с AsyncDisplayKitЯ получаю эту ошибку все время от ASDataController.mm:

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

у меня есть DataSourceManager класс, который содержит данные, и DatabaseManager это обрабатывает fetch а также insert операции.

Исключение всегда происходит в _layoutNodesFromContexts:ofKind:completion:, Я пробовал любую комбинацию GCD, которую я знал (Serial, Concurrent, Barrier), но я не смог справиться с этим исключением.

Как мне справиться с этой ситуацией?

Спасибо!

2 ответа

Это наверное потому что AsyncDisplayKit (или же Texture сейчас) работает с несколькими фоновыми потоками, и ваши объекты области передаются между потоками. Вот почему IncorrectThreadException,

Чтобы передать ваши объекты области между потоками, используйте ThreadSafeReferenceнаряду с использованием realm.resolve где вы получаете доступ к своим объектам в AsyncDisplayKit.

Больше информации здесь.

Я попытался Unmanaged_RLMObject в качестве обходного пути. Unmanaged_RLMObject - это объект RLMObject, который еще не добавлен в RLMRealm.

Это работает, но я не думаю, что это хорошее решение.

Неуправляемые экземпляры RLMObject ведут себя точно так же, как обычные подклассы NSObject, и их можно безопасно передавать между потоками.

Источник

Я нашел быстрое и простое решение: вместо прямого доступа к вашей модели данных layoutSpecThatFitsметоды, которые вызываются в фоновом режиме, просто объявляют параметр, необходимый для модели, и устанавливают его в вашем методе инициализации. Тогда используйте это в layoutSpecThatFits по-прежнему.

Например:

Предположим, ваша модель данных Person

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

В вашем узле (CellNode, DisplayNode и т. Д.) В методе layoutSpecThatFit не обращайтесь напрямую к человеку, а вместо этого укажите свойство name который вы установили в init метод, затем используйте его так: -

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) {
// ---
}

}

Ссылка: Я нашел идею из этой статьи

Другие вопросы по тегам