我有一个自定义的NSView类定义为:
class MyView: NSView
{
var someText: NSString
override func didChangeValueForKey(key: String)
{
println( key )
super.didChangeValueForKey( key )
}
// other stuff
}
我希望能够做的是从这个类的外部更改someText的值,并让didChangeValueForKey注意someText已经改变,所以我可以,例如,为视图设置needsDisplay为true,并做一些其他的工作。
我是怎么做到的?
答案 0 :(得分:4)
你确定你需要KVC吗? KVC在Swift中运行良好,但有一种更简单的方法:
var SomeText: NSString {
didSet {
// do some work every time SomeText is set
}
}
答案 1 :(得分:2)
没有KVC机制,因为这不是KVC的用途。
在Objective-C中,你可以显式地实现setter(如果属性最初是来自超类,则覆盖)并在那里完成你的工作。
在Swift中,正确的方法是didSet
机制。
didChangeValueForKey()
不是KVC的一部分,它是KVO(Key-Value Observing)的一部分。它无意被覆盖。当人们实施手动更改通知时(与willChangeValueForKey()
配对),它会被调用。
但更重要的是,没有理由相信任何东西都没有被观察到的财产。 KVO调用该类以便为实际被观察的那些属性挂钩到setter和其他变异访问器 。当更改此类属性(并支持自动更改通知)时,KVO会自动调用willChangeValueForKey()
和didChangeValueForKey()
。但是对于非观察到的属性,不会调用这些方法。
最后,在某些情况下,例如索引集合变异访问器,KVO将使用不同的更改通知方法,例如willChange(_:valuesAtIndexes:forKey:)
和didChange(_:valuesAtIndexes:forKey:)
。
如果您因某些原因确实不想使用didSet
,您可以使用KVO观察self
someText
属性中的更改并处理observeValueForKeyPath(_:ofObject:change:context:)
中的更改1}}。但这是一种糟糕,笨拙,容易出错,效率低下的简单方法。
答案 2 :(得分:1)
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"
答案 3 :(得分:0)
我会添加Jaanus的答案,为了使属性符合KVC,您应该将其声明为dynamic var someText: NSString
。
但如果你不需要所有的花里胡哨哦KVC,didSet
就是你要走的路。
<强>更新强>
对于didChangeValueForKey:
- 它的目的是相反,因为你通知key的值已经改变(如果它不是由于Foundation所涵盖的一个案例)。您应该使用addObserver(_:forKeyPath:options:context:)
并覆盖observeValueForKeyPath(_:ofObject:change:context:)
以获得更改通知。
或者,您可以使用许多第三方解决方案之一,例如ReactiveCococa或Facebook&#39; KVOController