KVO对Swift的计算属性

时间:2016-04-11 17:37:14

标签: ios swift key-value-observing foundation computed-properties

只是想知道这是否可以在Swift 2.2,KVO中计算属性!?

即:

   var width = 0
   var height = 0

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

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

客户端代码是否会修改with或height触发器observeValueForKeyPath?

在参与市长类重构之前先检查一下。 KVO的语法很烦人,因为如果有人手头的答案(我假设答案是否定的),它甚至不值得去游乐场。

问候! 〜d

3 个答案:

答案 0 :(得分:14)

该代码因两个原因而失败:

  1. 您必须将dynamic属性添加到area属性,如“Adopting Cocoa Design Patterns” in Using Swift with Cocoa and Objective-C下的“键值观察”部分所述。

  2. 您必须声明area取决于widthheight,如“Registering Dependent Keys” in the Key-Value Observing Programming Guide中所述。 (这适用于Objective-C和Swift。)为此,您还必须将dynamic添加到widthheight

    (无论何时willChangeValueForKeydidChangeValueForKey发生变化,您都可以致电widthheight,但通常更容易实施keyPathsForValuesAffectingArea。 )

  3. 因此:

    class MyObject: NSObject {
    
        dynamic var width: Double = 0
        dynamic var height: Double = 0
    
        dynamic private var area: Double {
            return width * height
        }
    
        class func keyPathsForValuesAffectingArea() -> Set<String> {
            return [ "width", "height" ]
        }
    
        func register() {
            self.addObserver(self, forKeyPath: "area", options: [ .Old, .New ], context: nil)
        }
    
        override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
            print("observed \(keyPath) \(change)")
        }
    
    }
    
    let object = MyObject()
    object.register()
    object.width = 20
    object.height = 5
    

    输出:

    observed Optional("area") Optional(["old": 0, "new": 0, "kind": 1])
    observed Optional("area") Optional(["old": 0, "new": 100, "kind": 1])
    

答案 1 :(得分:1)

正如@Rob在回答中所述,从Objective-c

中观察area dynamic

现在为willSet { }didSet { }属性添加widthheight
两个属性的willSet内添加此self.willChangeValueForKey("area") 并在didSet添加self.didChangeValueForKey("area");

现在,每当宽度或高度发生变化时,area的观察者都会收到通知。

注意:此代码未经过测试,但我认为它应该做到预期的

答案 2 :(得分:0)

为了避免 willChangeValueForKeydidChangeValueForKey 使用未经检查的字符串属性名称,我现在通常做的是制作计算属性 private(set) 并创建一个私有的 func 来更新它。

import Foundation

class Foo: NSObject {

    @objc dynamic private(set) var area: Double = 0
    @objc dynamic var width: Double = 0 { didSet { updateArea() } }
    @objc dynamic var height: Double = 0 { didSet { updateArea() } }

    private func updateArea() {
        area = width * height
    }
}