UserDefaults.didChangeNotification не срабатывает

В проекте, над которым я работаю, есть расширение, которое записывает данные в UserDefaults. Затем в содержащем приложении пользовательский интерфейс должен обновляться в соответствии с изменениями. Проблема в том, что UserDefaults.didChangeNotification не срабатывает, если только экран не исходит из фона. В чем может быть причина и есть ли способ исправить или еще как получить нужное обновление?

Запись данных в расширение:

let sharedUserDefaults = UserDefaults(suiteName: Common.UserDefaultsSuite)
var receivedNotifications = sharedUserDefaults?.array(forKey: Common.ReceivedNotifications)
if receivedNotifications != nil {
    receivedNotifications?.append(aData)
} else {
    receivedNotifications = [aData]
}
sharedUserDefaults?.set(receivedNotifications, forKey: Common.ReceivedNotifications) 

Регистрация для уведомления в контроллере представления:

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange), name: UserDefaults.didChangeNotification, object: nil)

}

И работа с измененными пользовательскими настройками по умолчанию (которые на самом деле не вызываются):

@objc func userDefaultsDidChange(_ notification: Notification) {

    print("User defaults did change")
    gatherReceivedNotifications()

}

person surToTheW    schedule 04.07.2018    source источник


Ответы (2)


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

override func viewDidLoad() {
    super.viewDidLoad()

    UserDefaults(suiteName: Common.UserDefaultsSuite)?.addObserver(self, forKeyPath: Common.ReceivedNotifications, options: .new, context: nil)

}

Затем реализован observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?):

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == Common.ReceivedNotifications {
        gatherReceivedNotifications()
    }
}

Он запускается немедленно и только тогда, когда внесены изменения в UserDefaults для ключа Common.ReceivedNotifications.

person surToTheW    schedule 04.07.2018

Код #selector(userDefaultsDidChange) означает func userDefaultsDidChange() без параметра.

Но вы определили func userDefaultsDidChange(_ notification: Notification), у него один параметр.

Следующий шаг:

Изменение #selector(userDefaultsDidChange) на #selector(userDefaultsDidChange(_:)) может это исправить.

person Chunlei Wang    schedule 04.07.2018
comment
@LeonardoHammer Спасибо за ответ, я попробовал, и никаких изменений. Все еще не запускает событие. - person surToTheW; 04.07.2018
comment
Вероятно, это: это уведомление не публикуется, когда изменения вносятся вне текущего процесса или когда меняются вездесущие значения по умолчанию. Вы можете использовать наблюдение за ключом и значением, чтобы зарегистрировать наблюдателей для определенных интересующих ключей, чтобы получать уведомления обо всех обновлениях, независимо от того, вносятся ли изменения в текущий процесс или за его пределами. из developer.apple.com/documentation/foundation/userdefaults/, т.е. если вы измените значение по умолчанию из другого процесса (например, расширения), вы не увидите изменения, если не соблюдаете ключ в соответствии с принятым ответом - person Red Nightingale; 15.06.2020