2017-01-21 3 views
3

Я заметил много проблем с доступом к объекту realm, и я думал, что мое решение будет решать это.Область, доступная из неправильной нити - снова

Так я написал простой метод Порции так:

public func write(completion: @escaping (Realm) ->()) { 
    DispatchQueue(label: "realm").async { 
     if let realm = try? Realm() { 
      try? realm.write { 
       completion(realm) 
      } 
     } 
    } 
} 

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

ошибка К сожалению, я получаю:

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

Хорошо, что делает 'завершение'? – EpicPandaForce

ответ

2

Ваш метод создает новый DispatchQueue каждый раз, когда вы называете его.

DispatchQueue(name:"") - это инициализатор, а не поиск. Если вы хотите, чтобы вы всегда были в одной очереди, вам нужно сохранить ссылку на эту очередь и отправить ее.

Вы должны создать очередь при настройке Царства и сохранить его как свойство класса, который выполняет настройку.

9

Экземпляры Realm и Object являются нитями. Они не могут быть переданы между потоками или это исключение произойдет.

Поскольку вы передаете сам completion в фоновый режим, в то же время создается очередь (как сказал Дейв Уэстон), любые объекты Realm внутри этого блока, наверняка, не были бы созданы в одном потоке , что объясняет эту ошибку.

Как сказал Дейв, вы создаете новую очередь отправки каждый раз, когда вы вызываете этот метод. Но, чтобы расширить это, iOS также не гарантирует, что одна очередь будет последовательно вызываться в одном потоке.

Как таковая, лучшая практика с Realm заключается в том, чтобы воссоздать объекты Realm в том же потоке каждый раз, когда вы хотите выполнить новую операцию над этим потоком. Realm внутренне кэширует экземпляры Realm по отдельности, поэтому очень мало накладных расходов связано с вызовом Realm() несколько раз.

Чтобы обновить определенный объект, вы можете использовать the new ThreadSafeReference feature для повторного доступа к одному и тому же объекту в фоновом потоке.

let realm = try! Realm() 
let person = Person(name: "Jane") // no primary key required 
try! realm.write { 
    realm.add(person) 
} 
let personRef = ThreadSafeReference(to: person) 
DispatchQueue(label: "com.example.myApp.bg").async { 
    let realm = try! Realm() 
    guard let person = realm.resolve(personRef) else { 
    return // person was deleted 
    } 
    try! realm.write { 
    person.name = "Jane Doe" 
    } 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^