首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用KVC实现单例模式

用KVC实现单例模式
EN

Stack Overflow用户
提问于 2017-12-06 01:55:38
回答 1查看 548关注 0票数 1

我的问题是,是否可以在Swift上的Singleton属性上使用KVC。我在测试一个类上的KVC,它能够工作,但是决定看看它是否能在Singleton类上工作。

我遇到一个错误,说明我的Singleton的“共享”属性不兼容KVC。

代码语言:javascript
复制
 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
   }
 }

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

NetworkCollectionTest9714 Test9714:452848*终止应用程序,原因是:‘addObserver: forKeyPath:@shared.fontSize“选项:3上下文:0x0被发送到一个不符合KVC的对象,该对象与”共享“属性不兼容。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-06 02:20:39

关键路径不正确。我是KVOObject.fontSize。你需要把观察者添加到这个单例中:

代码语言:javascript
复制
 KVOObject.shared.addObserver(self, forKeyPath: #keyPath(KVOObject.fontSize), options: [.old, .new], context: nil)

另外,(a)您可能应该使用上下文来确定您是否正在处理这个问题,或者它是否可能被超类使用;(b)如果super实现不是您的,则应该调用它;以及(c)确保删除deinit上的观察者

代码语言:javascript
复制
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超出范围时自动删除:

代码语言:javascript
复制
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,以避免可能导致子类化的混淆。

因此:

代码语言:javascript
复制
final class KVOObject: NSObject {
    static let shared = KVOObject()

    override private init() { super.init() }

    @objc dynamic var fontSize: Int = 18
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47665612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档