【问题标题】:Key-value observation weird behavior键值观察怪异行为
【发布时间】:2019-01-29 13:18:59
【问题描述】:

也许这个问题比我想象的更笼统,但我想确保我展示了我的完整背景,以防出现这个问题的原因。

  1. 我编写了一个带有符合 KVC 的属性和两个方法的单例类:
class Singleton: NSObject {
    static let sharedInstance = Singleton()

    @objc dynamic var aProperty = false

    func updateDoesntWork() {
        aProperty = !aProperty
    }

    func updateDoesWork() {
        Singleton.sharedInstance.aProperty = !aProperty
    }
}
  1. 我在我的应用委托的设置代码中为该属性添加了一个观察者:
Singleton.sharedInstance.addObserver(self, forKeyPath: #keyPath(Singleton.aProperty), options: [.new], context: nil)
  1. 我覆盖了我的应用代理的 observeValue() 方法:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    NSLog("observeValue(forKeyPath: \(String(describing:keyPath)), of: \(String(describing:object)), change: \(String(describing:change)), context:\(String(describing:context)))")
}

现在,如果我打电话给Singleton.sharedInstance.updateDoesntWork(),我不会得到aProperty 中更改的日志条目。属性发生了变化(我在调试器中验证了这一点),只是没有发送通知。

然而,如果我调用Singleton.sharedInstance.updateDoesWork(),一切都会按我的预期运行——当然,属性也发生了变化,但最重要的是,这次通知观察者发生了变化(打印了日志条目)。

对我来说,我应该需要完整的 Singleton.sharedInstance.aProperty 而不仅仅是 aProperty 才能使 KVO 工作,这对我来说毫无意义。我错过了什么?

【问题讨论】:

  • 我无法重现这个。两种方法都可以为我记录,没有麻烦。我会尝试将其精确到您在此处描述的内容,并在一个小型测试应用程序中进行尝试。例如,这是我使用的游乐场(我也在 iOS 应用中使用 app 委托进行了测试):gist.github.com/rnapier/4500b87cd3a253020be56e8bd03f54d3 最可能的原因是您没有观察到您认为自己是的对象,或者您正在调用updateDoesntWork 在你观察之前。
  • 这里也一样。无法重现(在命令行应用程序中)。
  • 请注意,如果不将 Singleton 的初始化程序设为私有,您实际上并不能保证只会创建 shared 实例,您只能保证您始终可以访问该实例具体实例。此外,你为什么不使用 Swift 4 的 KVO 而不是旧的 Obj-C 呢?见Key-Value Observing in Swift
  • @swineone: ...这意味着您在上面发布的不是显示问题行为的真实代码。
  • @MartinR 确实如此,对此我深表歉意。如果我真的尝试创建一个真正的 MCVE,我会发现我在我的应用程序委托中写 var singleton = Singleton() 的部分,而不是正确的 var singleton = Singleton.sharedInstance,我什至不会问这个问题。我的错。

标签: swift macos key-value-observing kvc


【解决方案1】:

我假设您无法将“var”用于单例。您可以考虑使用以下 sn-p 创建单例并初始化一些值,包括单例专用的观察:

class Singleton: NSObject {
    static private var sharedInstanceObserver : NSKeyValueObservation!

    static let sharedInstance: Singleton = {
        let sInstance = Singleton()
        sharedInstanceObserver = sInstance.observe(\Singleton.aProperty, options: .new) { st, value in
            print(st, value)
        }
        return sInstance
    }()

    @objc dynamic var aProperty = false

    func updateDoesntWork() {
        aProperty = !aProperty
    }

    func updateDoesWork() {
        Singleton.sharedInstance.aProperty = !aProperty
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    相关资源
    最近更新 更多