3

frage ich mich nur, ob dies in Swift 2.2 möglich ist, KVO auf einer berechneten Eigenschaft !?KVO auf Swifts berechneten Eigenschaften

dh:

var width = 0 
    var height = 0 

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

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

Würde ein Client-Code mit dem Trigger oder Höhe observeValueForKeyPath Modifizieren?

Überprüfen Sie, bevor Sie sich auf einen Refektor der Bürgermeisterklasse einlassen. KVO-Syntax ist so nervig wie es ist, ist nicht einmal einen Spielplatz wert, wenn jemand eine Antwort zur Hand hat (ich nehme an, Antwort ist NEIN)

Grüße! ~ d

+0

Die KVO alles über die Setter ist, wo Ihr Setter @dhomes ist? –

+1

Werfen Sie einen Blick auf ['RxSwift'] (https://github.com/ReactiveX/RxSwift). – dfri

+0

@Basheer_CAD das ist der Punkt! ich verweise kann man eine schreibgeschützte berechnete Eigenschaft beobachten? Würde die Einstellung der Breite oder Höhe eine neue Bereichsberechnung auslösen? (würde annehmen, nein, aber vielleicht ein schicker Compiler ????) –

Antwort

9

Dieser Code wird aus zwei Gründen nicht funktionieren:

  1. Sie müssen das dynamic Attribut auf die area Eigenschaft hinzufügen, wie im Abschnitt unter “Adopting Cocoa Design Patterns” in Using Swift with Cocoa and Objective-C „Schlüsselwert Beobachten“.

  2. Sie müssen erklären, dass area auf width abhängt und height wie in “Registering Dependent Keys” in the Key-Value Observing Programming Guide beschrieben. (Dies gilt für Objective-C und Swift.) Und damit das funktioniert, müssen Sie auch dynamic zu width und height hinzufügen.

    (Sie könnten stattdessen rufen willChangeValueForKey und didChangeValueForKey, wenn width oder height Veränderungen, aber es ist in der Regel einfacher, nur keyPathsForValuesAffectingArea zu implementieren.)

So:

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 

Ausgang:

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

Ich glaube, dass nach den gleichen Dokumentations-Links, sollten Sie den Kontext angeben, nein? – MarqueIV

+1

Normalerweise ist es eine gute Idee, einen 'Kontext' aus mehreren Gründen zu verwenden, aber diese Antwort war nicht über diesen Teil von KVO. Wenn Sie nur von "NSObject" erben, müssen Sie keinen "Kontext" verwenden, es sei denn, Sie möchten das, weil "NSObject" für keine KVO-Benachrichtigungen registriert wird. Es gibt also keine Möglichkeit, Konflikte mit Ihrer Oberklasse zu verursachen. –

+0

Gute Info! Danke für das Teilen! – MarqueIV

1

Wie @ Rob in seiner Antwort erwähnt, machen areadynamic von Objective-c beobachtet werden

Jetzt willSet { } und didSet { } für width und height Eigenschaften,
innen willSet hinzufügen für beide Eigenschaften dieses self.willChangeValueForKey("area") hinzufügen und in didSet hinzufügen self.didChangeValueForKey("area");

Nun werden Beobachter von area jedes Mal benachrichtigt, wenn sich die Breite oder Höhe ändert.

Hinweis: Dieser Code ist nicht getestet, aber ich denke, es sollte das tun, was erwartet