[英]NSView with a KVC property in Swift
我有一个自定义的NSView类,定义为:
class MyView: NSView
{
var someText: NSString
override func didChangeValueForKey(key: String)
{
println( key )
super.didChangeValueForKey( key )
}
// other stuff
}
我想要做的是从此类外部更改someText的值,并didChangeValueForKey注意到someText已更改,因此我可以例如将视图的needsDisplay设置为true并执行其他一些工作。
我该怎么做?
您确定为此需要KVC吗? KVC在Swift中可以正常工作,但是有一种更简单的方法:
var SomeText: NSString {
didSet {
// do some work every time SomeText is set
}
}
没有KVC机制,因为这不是KVC的目的。
在Objective-C中,您将显式实现setter(如果该属性最初来自超类,则可以重写该setter)并在那里进行工作。
在Swift中,正确的方法是didSet
机制。
didChangeValueForKey()
不是KVC的一部分,而是KVO(键值观察)的一部分。 不应覆盖它。 它旨在在实现手动更改通知时(与willChangeValueForKey()
配对willChangeValueForKey()
被调用。
但是,更重要的是,没有理由相信对于任何事物都不会观察到的属性,将完全调用它。 KVO使类陷入混乱,以便针对实际观察到的那些属性挂接到setter和其他变异访问器中 。 更改此类属性(并支持自动更改通知)后,KVO会自动调用willChangeValueForKey()
和didChangeValueForKey()
。 但是对于不可观察的属性,不会调用这些方法。
最后,在某些情况下,例如索引集合突变访问器,KVO将使用不同的更改通知方法,例如willChange(_:valuesAtIndexes:forKey:)
和didChange(_:valuesAtIndexes:forKey:)
。
如果由于某些原因确实不想使用didSet
,则可以使用KVO来观察self
对someText
属性的更改,并处理observeValueForKeyPath(_:ofObject:change:context:)
。 但这是一种不好的,笨拙的,容易出错的,低效的简单方法。
KVO和didSet
不互斥:
import Foundation
class C: NSObject {
dynamic var someText: String = "" {
didSet {
print("changed to \(someText)")
}
}
}
let c = C()
c.someText = "hi" // prints "changed to hi"
class Observer: NSObject {
init(_ c: C) {
super.init()
c.addObserver(self, forKeyPath: "someText", options: [], context: nil)
}
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
print("observed change to \(object!.valueForKeyPath(keyPath!))")
}
}
let o = Observer(c)
c.someText = "test" // prints "changed to test" and "observed change to test"
我要在Jaanus的答案中添加一点,要使属性KVC兼容,您应该将其声明为dynamic var someText: NSString
。
但是,如果您不需要KVC的所有didSet
功能, didSet
是您的最佳选择。
更新资料
至于didChangeValueForKey:
–相反,它旨在通知您密钥的值已更改(如果不是由于Foundation涵盖的情况之一)。 您应该使用addObserver(_:forKeyPath:options:context:)
并重写observeValueForKeyPath(_:ofObject:change:context:)
来通知更改。
或者,您可以使用许多第三方解决方案之一,例如ReactiveCococa或Facebook的KVOController
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.