在Swift中使用KVC属性的NSView

时间:2015-08-30 18:49:24

标签: xcode swift cocoa kvc

我有一个自定义的NSView类定义为:

class MyView: NSView
{
    var someText: NSString

    override func didChangeValueForKey(key: String)
    {
        println( key )

        super.didChangeValueForKey( key )
    }

    // other stuff
}

我希望能够做的是从这个类的外部更改someText的值,并让didChangeValueForKey注意someText已经改变,所以我可以,例如,为视图设置needsDisplay为true,并做一些其他的工作。

我是怎么做到的?

4 个答案:

答案 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