У меня есть случай, когда мне нужно заполнить область серией объектов по запросу пользователя. Для заполнения области я делаю сетевой вызов, а затем записываю объекты в область. Когда запись завершена, фоновый поток вызывает обратный вызов, который переключается на основной поток для обработки результатов. Я бы предпочел использовать уведомления областей, но это очень конкретный c вариант использования, и уведомления не являются опцией.
Я не могу поделиться своим полным проектом, но мне удалось воспроизвести эту проблему с пример проекта. Вот моя модель данных.
class Owner: Object {
@objc dynamic var uuid: String = ""
@objc dynamic var name: String = ""
convenience init(uuid: String, name: String) {
self.init()
self.uuid = uuid
self.name = name
}
func fetchDogs() -> Results<Dog>? {
return realm?.objects(Dog.self).filter("ownerID == %@", uuid)
}
override class func primaryKey() -> String? {
return "uuid"
}
}
class Dog: Object {
@objc dynamic var uuid: String = ""
@objc dynamic var name: String = ""
@objc dynamic var ownerID: String = ""
func fetchOwner() -> Owner? {
return realm?.object(ofType: Owner.self, forPrimaryKey: ownerID)
}
convenience init(uuid: String, name: String, ownerID: String) {
self.init()
self.uuid = uuid
self.name = name
self.ownerID = ownerID
}
override class func primaryKey() -> String? {
return "uuid"
}
}
Я понимаю, что List
будет подходящим для отношения Owner
-> Dog
, но это не вариант в этом проекте.
В примере проекта есть две кнопки, которые нас интересуют. Один для добавления некоторых Dog
объектов в область и связывания их с Owner
UUID. Другая кнопка удаляет все Dog
объекты, принадлежащие владельцу.
Основной поток c выглядит следующим образом:
- Удаление всех собак владельца
- Создайте новый набор собак в фоновом потоке и добавьте их в область.
- Вызовите обратный вызов
- Переключитесь обратно в основной поток
- Распечатайте все собаки владельца
Девять раз из десяти собак были успешно распечатаны. Однако иногда область указывает на то, что с текущим владельцем не связано ни одной собаки. Что может быть причиной этого? Мой логик контроллера вида c ниже.
РЕДАКТИРОВАТЬ: Последнее, что я должен упомянуть, это то, что эта проблема воспроизводится только на физическом устройстве. Я не могу воспроизвести это на симуляторе. Это заставляет меня задуматься, если это ошибка в области.
// MARK: - Props and view controller life cycle
class ViewController: UIViewController {
var owner: Owner?
let ownerUUID = UUID().uuidString
override func viewDidLoad() {
super.viewDidLoad()
owner = makeOwner()
}
}
// MARK: - Action methods
extension ViewController {
@IBAction func onDeletePressed(_ sender: UIButton) {
print("Deleting...")
deleteDogs()
}
@IBAction func onRefreshPressed(_ sender: UIButton) {
print("Creating...")
createDogs {
DispatchQueue.main.async {
self.printDogs()
}
}
}
@IBAction func onPrintPressed(_ sender: UIButton) {
printDogs()
}
}
// MARK: - Helper methods
extension ViewController {
private func makeOwner() -> Owner? {
let realm = try! Realm()
let owner = Owner(uuid: ownerUUID, name: "Bob")
try! realm.write {
realm.add(owner)
}
return owner
}
private func deleteDogs() {
guard let dogs = owner?.fetchDogs() else { return }
let realm = try! Realm()
try! realm.write {
realm.delete(dogs)
}
}
private func createDogs(completion: @escaping () -> Void) {
DispatchQueue(label: "create.dogs.background").async {
autoreleasepool {
let realm = try! Realm()
let dogs = [
Dog(uuid: UUID().uuidString, name: "Fido", ownerID: self.ownerUUID),
Dog(uuid: UUID().uuidString, name: "Billy", ownerID: self.ownerUUID),
Dog(uuid: UUID().uuidString, name: "Sally", ownerID: self.ownerUUID),
]
try! realm.write {
realm.add(dogs)
}
}
completion()
}
}
private func printDogs() {
guard let dogs = owner?.fetchDogs() else { return }
print("Dogs: \(dogs)")
}
}