Skip to content

Instantly share code, notes, and snippets.

@angelolloqui
Last active March 7, 2019 20:41
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save angelolloqui/85457208234e6ac024557afa99632d2e to your computer and use it in GitHub Desktop.
Save angelolloqui/85457208234e6ac024557afa99632d2e to your computer and use it in GitHub Desktop.
Swift KVO extension to provide track on addObserver and removeObserver methods, avoiding the annoying crashes due to observers not register
// Created by Angel Garcia on 06/05/16.
import Foundation
extension NSObject {
private struct AssociatedKeys {
static var safeObservers = "safeObservers"
}
private var safeObservers: [ObserverInfo] {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.safeObservers) as? [ObserverInfo] ?? []
}
set (new) {
objc_setAssociatedObject(self, &AssociatedKeys.safeObservers, new, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
func addSafeObserver(observer: NSObject, forKeyPath keyPath: String, options: NSKeyValueObservingOptions) {
let observerInfo = ObserverInfo(observer: observer, keypath: keyPath)
if !self.safeObservers.contains(observerInfo) {
self.safeObservers.append(ObserverInfo(observer: observer, keypath: keyPath))
self.addObserver(observer, forKeyPath: keyPath, options: options, context: nil)
}
}
func removeSafeObserver(observer: NSObject, forKeyPath keyPath: String) {
let observerInfo = ObserverInfo(observer: observer, keypath: keyPath)
if self.safeObservers.contains(observerInfo) {
self.safeObservers.remove(observerInfo)
self.removeObserver(observer, forKeyPath: keyPath)
}
}
}
private class ObserverInfo: Equatable {
let observer: UnsafePointer<Void>
let keypath: String
init(observer: NSObject, keypath: String) {
self.observer = unsafeAddressOf(observer)
self.keypath = keypath
}
}
private func ==(lhs: ObserverInfo, rhs: ObserverInfo) -> Bool {
return lhs.observer == rhs.observer && lhs.keypath == rhs.keypath
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment