3

просто интересно, возможно ли это в Swift 2.2, KVO на вычисленном свойстве !?KVO на вычисляемые свойства Swift

т.е.

var width = 0 
    var height = 0 

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

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

Будет ли клиент код модификации с или спускового высота observeValueForKeyPath?

Просто проверите перед тем, как принять участие в рефакторе класса мэра. Синтаксис KVO как раздражающий, так как он не стоит даже игровой площадки, если у кого-то есть ответ под рукой (я принимаю ответ НЕТ)

привет! ~ d

+0

KVO все о инкубаторе, где находится ваш сеттер @dhomes? –

+1

Посмотрите на ['RxSwift'] (https://github.com/ReactiveX/RxSwift). – dfri

+0

@Basheer_CAD вот в чем смысл! Я имею в виду, можно ли наблюдать вычислимое свойство только для чтения? будет ли установка ширины или высоты инициировать новый расчет области? (предположил бы нет, но может быть, какой-то фантастический компилятор ????) –

ответ

9

Этот код не будет работать по двум причинам:

  1. Вы должны добавить атрибут dynamic к area собственности, как описано в разделе «Key-Value Соблюдая» под “Adopting Cocoa Design Patterns” in Using Swift with Cocoa and Objective-C.

  2. Вы должны объявить, что area зависит от width и height, как описано в “Registering Dependent Keys” in the Key-Value Observing Programming Guide. (Это относится к Objective-C и Swift.) И для этого вам также необходимо добавить dynamic в width и height.

    (Вы могли бы вместо того, чтобы позвонить willChangeValueForKey и didChangeValueForKey всякий раз, когда width или height изменения, но это, как правило, легче всего реализовать keyPathsForValuesAffectingArea.)

Таким образом:

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

Я верю, согласно тем же ссылкам документации, вы должны указать контекст, нет? – MarqueIV

+1

Обычно полезно использовать «контекст» по нескольким причинам, но этот ответ не касался этой части KVO. Кроме того, если вы только наследуете «NSObject», вам не нужно использовать «контекст», если вы этого не хотите, потому что «NSObject» не регистрируется для каких-либо уведомлений KVO, поэтому нет возможности конфликта с вашим суперклассом. –

+0

Хорошая информация! Спасибо, что поделился! – MarqueIV

1

Как заявил @Rob в своем ответе, сделать areadynamic наблюдаться из Objective-C

Теперь добавьте willSet { } и didSet { } для width и height свойств,
внутри willSet для обоих свойств добавить self.willChangeValueForKey("area") и в didSet добавить self.didChangeValueForKey("area");

Теперь наблюдатели от area будут уведомлены обо всех разностях при изменении ширины или высоте.

Примечание: этот код не проверял, но я думаю, что он должен делать то, что ожидалось