Observation of NSUserDefaults does not work when using .init(suitename:)

Viewed 176

If I use the default UserDefaults I can subscribe to changes via keypath to specific changes. However, if I use a UserDefaults instance created with the init(suiteName:), no changes are delivered.

According to the MAC Os release notes, the problem was fixed a while ago. However, I cannot confirm this. Does anyone know the problem and possibly a solution for it?

In previous releases, KVO could only be used on the instance of NSUserDefaults returned by the +standardUserDefaults method. Additionally, changes from other processes (such as defaults(1), extensions, or other apps in an app group) were ignored by KVO. These limitations have both been corrected. Changes from other processes will be delivered asynchronously on the main queue, and ignore NSKeyValueObservingOptionPrior.

https://developer.apple.com/library/archive/releasenotes/Miscellaneous/RN-Foundation-OSX10.12/index.html

Code Example:

    import UIKit
    import Combine
    import Foundation
    
    @main
    class AppDelegate: UIResponder, UIApplicationDelegate {
        let provider = CalendarProvider()
    }
    
    extension UserDefaults {
        @objc dynamic var startOfTheWeek: Int {
            return integer(forKey: "startOfTheWeek")
        }
    }
    
    final class CalendarProvider: ObservableObject {
        @Published var currentCalendar: Calendar = Calendar.current
        private var observer: NSKeyValueObservation?
        
        init() {
            var calendar = Calendar(identifier: .gregorian)
            calendar.firstWeekday = 1
            self.currentCalendar = calendar
        
            observer = UserDefaults(suiteName: "group.foo.com")?
                .observe(\.startOfTheWeek, options: [.new , .initial],
                                                     changeHandler: { (defaults, change) in
                DispatchQueue.main.async {
                    var calendar = Calendar(identifier: .gregorian)
                    calendar.firstWeekday = change.newValue ?? 1
                    self.currentCalendar = calendar
                }
            })
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
                UserDefaults(suiteName: "group.foo.com")?.setValue(8, forKey: "startOfTheWeek")
            })
        }
        
        deinit {
            observer?.invalidate()
        }
    }
0 Answers
Related