推送扩展到 App 触发 KVO

Triggering KVO from Push Extension to App

我正在尝试在主应用程序中实现 KVO 并观察扩展何时更改值。 收到推送时主应用程序打开,但主应用程序中没有触发。只有当我关闭并打开它时,我才能看到变化。

通知Class:

class NotificationService: UNNotificationServiceExtension {

var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?


override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {

    self.contentHandler = contentHandler
    bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

    if let bestAttemptContent = bestAttemptContent {

        var user = (bestAttemptContent.userInfo["user"] as! String?)!
        let userDefaults = UserDefaults(suiteName: "group.com.test.apps")
        userDefaults!.set(user as String, forKey: "User")
        userDefaults!.synchronize()
        contentHandler(bestAttemptContent)
    }
}
}

主要ViewController:

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

     let userDefaults = UserDefaults(suiteName: "group.com.test.apps")
    userDefaults!.addObserver(self, forKeyPath: "User", options: NSKeyValueObservingOptions.new, context: nil)

}

 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

    //Not triggered
    let userDefaults = UserDefaults(suiteName: "group.com.test.apps")
    let user = userDefaults!.string(forKey: "User")
    NSLog("User \(user)")

}
}

您使用的是 iOS 10 或更高版本吗? KVO 跨进程(比如扩展)直到 10 才起作用。https://developer.apple.com/library/archive/releasenotes/Miscellaneous/RN-Foundation-OSX10.12/index.html,搜索"Key-Value Observing and NSUserDefaults"

套件的UserDefault不是共享实例,所以你必须保留它,否则它只是被释放。

这里是固定的App端控制器。使用 Xcode 11.4 / iOS 13.4

测试

注意:KVO 仅在设置了真正的新值时才起作用,因此如果在您的扩展中将相同的值设置为 UserDefaults,则不会通知观察者。

class ViewController: UIViewController {

  // keep suite instance as member
  let userDefaults = UserDefaults(suiteName: "group.com.test.apps")

  override func viewDidLoad() {
    super.viewDidLoad()

    userDefaults!.addObserver(self, forKeyPath: "User", options: [.new], context: nil)
  }

  override func observeValue(forKeyPath keyPath: String?, of object: Any?, 
       change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {

    let user = userDefaults!.string(forKey: "User")
    NSLog("User \(user)")

  }
}