将KVC与单例模式使用



我的问题是关于是否可以在Swift上的Singleton属性上使用KVC。我在课堂上测试KVC可以使它起作用,但决定查看它是否在Singleton课程上起作用。
我遇到了一个错误,说明我的单例的"共享"属性不符合KVC。

 class KVOObject: NSObject {
    @objc static let shared = KVOObject()
    private override init(){}
    @objc dynamic var fontSize = 18
 }
 override func viewDidLoad() {
    super.viewDidLoad()
    addObserver(self, forKeyPath: #keyPath(KVOObject.shared.fontSize), options: [.old, .new], context: nil) 
 }
 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
   if keyPath == #keyPath(KVOObject.shared.fontSize) {
      // do something
   }
 }

我目前正在遇到以下错误:

NetworkCollectionTest [9714:452848] ***由于未知的例外'NSunknowneKeyException'终止应用程序'不适合"共享"属性的KVC。'

关键路径不正确。是KVOObject.fontSize。而且您需要将观察者添加到那个单身人士:

 KVOObject.shared.addObserver(self, forKeyPath: #keyPath(KVOObject.fontSize), options: [.old, .new], context: nil)

顺便说一句,(a)您可能应该使用上下文来确定您是否正在处理此问题,或者超级类是否可以使用它;(b)如果不是您的,则应致电super实现;(c)确保在deinit上删除观察者:

class ViewController: UICollectionViewController {
    private var observerContext = 0
    override func viewDidLoad() {
        super.viewDidLoad()
        KVOObject.shared.addObserver(self, forKeyPath: #keyPath(KVOObject.fontSize), options: [.new, .old], context: &observerContext)
    }
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if context == &observerContext {
            // do something
        } else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
        }
    }
    deinit {
        KVOObject.shared.removeObserver(self, forKeyPath: #keyPath(KVOObject.fontSize))
    }
    ...
}

或者,如果在Swift 4中,它现在要容易得多,因为它是基于封闭的(避免需要上下文),并且当NSKeyValueObservation脱离范围时会自动删除:

class ViewController: UICollectionViewController {
    private var token: NSKeyValueObservation?
    override func viewDidLoad() {
        super.viewDidLoad()
        token = KVOObject.shared.observe(.fontSize, options: [.new, .old]) { [weak self] object, change in
            // do something
        }
    }
    ...
}

顺便说一句,对单人的一些观察:

  1. shared属性不需要@objc预选赛;只有被观察到的财产需要;和

  2. init方法确实应该调用super;和

  3. 我可能还将其声明为 final

因此:

final class KVOObject: NSObject {
    static let shared = KVOObject()
    override private init() { super.init() }
    @objc dynamic var fontSize: Int = 18
}

最新更新