Created
February 1, 2017 20:57
-
-
Save swillits/93206997e7d1bff4d08e24e23173820e to your computer and use it in GitHub Desktop.
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
class Receptionist: NSObject { | |
typealias KVOReceptionistBlock = (Info) -> () | |
private var opQueue: OperationQueue? = nil | |
private var kvoHandler: KVOReceptionistBlock! = nil | |
private var kvoObject: NSObject! = nil | |
private var kvoKeyPath: String! = nil | |
private var kvoContext: Int? = nil | |
private var activeLock = QueueLock() | |
private var _active = true | |
var active: Bool { | |
get { | |
return activeLock.getting { | |
return self._active | |
} | |
} | |
set { | |
activeLock.around { | |
self._active = newValue | |
} | |
} | |
} | |
struct Info { | |
let object: NSObject | |
let keyPath: String | |
let change: [NSKeyValueChangeKey : Any]? | |
} | |
init(forKeyPath keyPath: String, of object: NSObject, options: NSKeyValueObservingOptions, queue: OperationQueue?, handler: @escaping KVOReceptionistBlock) { | |
kvoHandler = handler | |
kvoObject = object | |
kvoKeyPath = keyPath | |
opQueue = queue | |
super.init() | |
kvoObject.addObserver(self, forKeyPath: kvoKeyPath, options: options, context: &kvoContext) | |
} | |
convenience init(forKeyPath keyPath: String, of object: NSObject, handler: @escaping KVOReceptionistBlock) { | |
self.init(forKeyPath: keyPath, of: object, options: NSKeyValueObservingOptions(), queue: nil, handler: handler) | |
} | |
deinit { | |
kvoObject.removeObserver(self, forKeyPath: kvoKeyPath, context: &kvoContext) | |
} | |
@objc override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | |
if context == &kvoContext { | |
if keyPath == kvoKeyPath { | |
if let handler = kvoHandler, active { | |
let info = Info(object: kvoObject, keyPath: kvoKeyPath, change: change) | |
if let queue = opQueue { | |
queue.addOperation { | |
handler(info) | |
} | |
} else { | |
handler(info) | |
} | |
} | |
} | |
} else { | |
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment