(см. Обновления ниже для получения более подробной информации.)
это странная проблема.Я не могу опубликовать все в своем классе (это слишком много), поэтому я попытаюсь охватить основные части:
У меня есть контроллер представления с viewDidLoad()
методом:
class MyClass {
...
override func viewDidLoad() {
super.viewDidLoad()
// mainViewContext is the viewContext passed by AppDelegate's persistentContainer
NotificationCenter.default.addObserver(self, selector: #selector(test(notif:)), name: Notification.Name.NSManagedObjectContextObjectsDidChange, object: mainViewContext)
}
...
@objc func test(notif: Notification) {
print("I got called")
}
...
Итак, я добавил наблюдателя, чтобы узнать, был ли изменен объект CoreData.Однако это уведомление не публикуется всегда.Когда я делаю это (например, в viewDidLoad()
сразу после добавления наблюдателя):
self.appDelegate.persistentContainer.performBackgroundTask({ (privateContext) in
// FileBrowserElement is a managed object I created
let folder = privateContext.object(with: App.rootFolderObjectID) as! FileBrowserElement
// Random number so that the name really changes everytime (so that there is something to change when saving)
folder.name = "newFolderName" + String(Int.random(between: 0, and: 90000))
do {
try privateContext.save()
} catch let error as NSError {
print("Error: " + error.debugDescription)
}
})
это работает.test(notif:)
вызывается.Но теперь я заменяю его следующим:
self.appDelegate.persistentContainer.performBackgroundTask({
(privateContext) in
// Just another type of managed object I have.
let folder = privateContext.object(with: App.templateRackObjectID) as! Rack
folder.name = "newFolderName" + String(Int.random(between: 0, and: 90000))
do {
try privateContext.save()
} catch let error as NSError {
print("Error: " + error.debugDescription)
}
})
И он больше не работает.test(notif:)
не вызывается.Я понятия не имею, почему это так.Я буквально изменил только изменяемый объект.
(я установил persistentContainer.viewContext.automaticallyMergesChangesFromParent = true
в AppDelegate)
Размещается ли уведомление только для некоторых типов управляемых объектов?Я что-то скучаю?Я не знаю, как начать отлаживать это.Я пытался часами.Это очень странно.
Есть мысли?Дайте мне знать, если вам нужна дополнительная информация.Как я уже сказал, я не знаю, что важно для этого вопроса.Весь класс был бы слишком большим, чтобы публиковать здесь.
ОБНОВЛЕНИЕ: Я попытался воссоздать эту проблему с фиктивным проектом.Странно, это не отправка уведомления ни с одним из управляемых объектов.Я загрузил его в github: https://github.com/d3mueller/NotificationTestProject
Может, я там что-то не так сделал, чего не вижу?
ОБНОВЛЕНИЕ 2 (что-то нашел. Я обновилрепо) Итак, это невероятно странно.У меня было подозрение, что оно оказалось правдоподобным (наверное).
Кажется, что уведомление отправляется только тогда, когда вы ранее загрузили тот же управляемый объект, который хотите изменить и получить доступ к его атрибуту.Я добавил это прямо перед запуском performBackgroundTask
:
// As a class attribute, I added `private var rack: Rack!`. Then this is in `viewDidLoad`, right before the background task
rack = mainViewContext.object(with: App.templateRackObjectID) as! Rack
_ = rack.name
Теперь все работает.Но почему?Это странно.Почему я должен получить к нему доступ раньше?Уведомление всегда должно быть отправлено.Есть мысли по этому поводу?Я добавил это в фиктивный проект на Github, если вы хотите попробовать его.
Буду очень признателен за любую помощь в этом:)