Created
March 14, 2016 08:06
-
-
Save danieleggert/f2f076476bb42754ee0c to your computer and use it in GitHub Desktop.
Type-safe KVO
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
/// A type-safe Key-Value-Observer (KVO). | |
/// | |
/// Extend the class to be observed to implement `KeyCodable`, e.g. | |
/// ``` | |
/// extension WKWebView: KeyCodable { | |
/// enum Key: String { | |
/// case estimatedProgress | |
/// } | |
/// } | |
/// ``` | |
/// and observe with | |
/// ``` | |
/// observer = KeyValueObserver(target: webView, key: .estimatedProgress, options: []) { [weak self] progress in | |
/// // do something with the value | |
/// } | |
/// ``` | |
final class KeyValueObserver<Target, Value where Target: NSObject, Target: KeyCodable, Target.Key.RawValue == String>: NSObject { | |
typealias blockType = ((Value) -> ()) | |
let target: Target | |
let key: Target.Key | |
let block: blockType | |
private var context: Int = 0 | |
init(target: Target, key: Target.Key, options: NSKeyValueObservingOptions, block: (Value) -> ()) { | |
self.target = target | |
self.key = key | |
self.block = block | |
super.init() | |
self.target.addObserver(self, forKeyPath: keyPath, options: options, context: &context) | |
} | |
deinit { | |
target.removeObserver(self, forKeyPath: keyPath) | |
} | |
override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, | |
change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { | |
guard context == context, | |
let object = object as? Target, | |
let keyPath = keyPath, | |
let value = object.valueForKeyPath(keyPath) as? Value else {return} | |
block(value) | |
} | |
} | |
protocol KeyCodable { | |
typealias Key: RawRepresentable | |
} | |
private extension KeyValueObserver { | |
var keyPath: String { | |
return key.rawValue | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment