-
-
Save alemar11/7ba16f2be8c9df6fe2802a596db7ef46 to your computer and use it in GitHub Desktop.
Type-safe KVO
This file contains 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