gpt4 book ai didi

ios - 将 KVC 与单例模式结合使用

转载 作者:搜寻专家 更新时间:2023-11-01 06:30:48 25 4
gpt4 key购买 nike

我的问题是关于是否可以在 Swift 的单例属性上使用 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] *** 由于未捕获的异常 'NSUnknownKeyException' 而终止应用程序,原因:'[addObserver: forKeyPath:@"shared.fontSize"options:3 context:0x0] 被发送到一个对象“共享”属性不符合 KVC。'

最佳答案

key 路径不正确。它是 KVOObject.fontSize。您需要将观察者添加到该单例中:

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

顺便说一句,(a) 您可能应该使用上下文来确定您是在处理这个还是它是否可能被父类(super class)使用; (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 限定符;只有被观察的属性(property)需要那个;和

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

  3. 我可能还会将其声明为 final 以避免可能导致子类化单例的混淆。

因此:

final class KVOObject: NSObject {
static let shared = KVOObject()

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

@objc dynamic var fontSize: Int = 18
}

关于ios - 将 KVC 与单例模式结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47665612/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com