kemchenj
9/12/2017 - 1:13 PM

KVO-Binding

通过 Swift 4 新增的 KeyPath,让 NSObject 拥有了类型安全的 KVO-Binding

https://twitter.com/chriseidhof/status/907232916555661312

import Foundation

extension NSObjectProtocol where Self: NSObject {

    func observe<A, Other>(_ keyPath: KeyPath<Self,A>,
                        writeTo other: Other,
                        _ otherKeyPath: ReferenceWritableKeyPath<Other,A>)
        -> NSKeyValueObservation
        where A: Equatable, Other: NSObjectProtocol 
    {
            return self.observe(keyPath, options: .new) { _, change in
                guard let newValue = change.newValue,
                    other[keyPath: otherKeyPath] != newValue else {
                        return // no change
                }
                other[keyPath: otherKeyPath] = newValue
            }
    }
 
    func bind<A, Other>(_ keyPath: ReferenceWritableKeyPath<Self,A>,
                           to other: Other,
                           _ otherKeyPath: ReferenceWritableKeyPath<Other,A>)
        -> (NSKeyValueObservation, NSKeyValueObservation)
        where A: Equatable, Other: NSObject
    {
        let one = self.observe(keyPath, writeTo: other, otherKeyPath)
        let two = other.observe(otherKeyPath, writeTo: self, keyPath)
        return (one,two)
    }
}
import Foundation

final class Sample: NSObject {
    @objc dynamic var name: String = ""
}

class MyObj: NSObject {
    @objc dynamic var test: String = ""
}

let sample = Sample()
let other = MyObj()

let observation = sample.bind(\Sample.name, to: other, \.test)
sample.name = "NEW"
other.test
other.test = "HI"
sample.name