Область в 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) {
// ---
}
}
Ссылка: Я нашел идею из этой статьи