Last active
March 7, 2019 20:41
-
-
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
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
// 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