13

Swiftで計算されたプロパティのKVOは可能ですか?

var width = 0
var height = 0

private var area : Double {
    get {
        return with * height
    }
}

self.addOberser(self, forKeyPath: "area", ......

with または height トリガーを変更するクライアント コードは、ValueForKeyPath を監視しますか?

市長クラスのリファクタリングに取り組む前に確認するだけです。KVO の構文は煩わしいものであり、誰かが答えを手元に持っている場合、遊び場でさえ価値がありません。(答えはNOだと思います)

4

3 に答える 3

22

このコードは、次の 2 つの理由で機能しません。

  1. Using Swift with Cocoa and Objective-Cの「Adopting Cocoa Design Patterns」のセクション「Key-Value Observing」で説明されているようにdynamic、プロパティに属性を追加する必要があります。area

  2. Key-Value Observing Programming Guideの「Registering Dependent Keys」で説明されているように、依存areaすることを宣言する必要があります。(これは、Objective-C と Swift に適用されます。) これが機能するには、 and にも追加する必要があります。widthheightdynamicwidthheight

    willChangeValueForKey(代わりにand didChangeValueForKeywhenwidthまたはchangesを呼び出すこともできますがheight、通常は単に実装する方が簡単keyPathsForValuesAffectingAreaです。)

したがって:

import Foundation

class MyObject: NSObject {

    @objc dynamic var width: Double = 0
    @objc dynamic var height: Double = 0

    @objc dynamic private var area: Double {
        return width * height
    }

    @objc class func keyPathsForValuesAffectingArea() -> Set<String> {
        return [ "width", "height" ]
    }

    func register() {
        self.addObserver(self, forKeyPath: "area", options: [ .old, .new ], context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        print("observed \(keyPath) \(change)")
    }
}

let object = MyObject()
object.register()
object.width = 20
object.height = 5

出力:

observed Optional("area") Optional([__C.NSKeyValueChangeKey(_rawValue: new): 0, __C.NSKeyValueChangeKey(_rawValue: kind): 1, __C.NSKeyValueChangeKey(_rawValue: old): 0])
observed Optional("area") Optional([__C.NSKeyValueChangeKey(_rawValue: new): 100, __C.NSKeyValueChangeKey(_rawValue: kind): 1, __C.NSKeyValueChangeKey(_rawValue: old): 0])
于 2016-04-11T17:49:00.710 に答える