Skip to content

Instantly share code, notes, and snippets.

@muukii
Created November 30, 2017 03:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save muukii/175c35879fbb1c541a9d19ff1717ad0f to your computer and use it in GitHub Desktop.
Save muukii/175c35879fbb1c541a9d19ff1717ad0f to your computer and use it in GitHub Desktop.
public final class ModelObserver {
deinit {
tokens.forEach {
notificationCenter.removeObserver($0)
}
}
// MARK: - Properties
private var tokens: [NSObjectProtocol] = []
private let observerIdentifier: String = UUID().uuidString
private let notificationCenter: NotificationCenter = .default
// MARK: - Initializers
init() {
}
// MARK: - Functions
func update<T: ModelObservableType>(_ model: T) {
let _key = notificationKey(model)
notificationCenter.post(name: .init(rawValue: _key), object: model)
}
func notificationKey<T: ModelObservableType>(_ model: T) -> String {
let modelName = String(reflecting: type(of: model))
let identifier = model.identifier
let key = "\(observerIdentifier).\(modelName).\(identifier)"
return key
}
@discardableResult
public func add<T: ModelObservableType>(model: T, didUpdate: @escaping (ModelObserver, T) -> Void) -> NSObjectProtocol {
model.addRecursiveModelObserve(observer: self)
let key = notificationKey(model)
let queue = OperationQueue.current ?? OperationQueue.main
let token = notificationCenter.addObserver(
forName: NSNotification.Name(rawValue: key),
object: nil,
queue: queue
) { [weak self] (notification) in
guard let `self` = self else { return }
if let model = notification.object.flatMap({ $0 as? T }) {
didUpdate(self, model)
}
}
tokens.append(token)
didUpdate(self, model)
return token
}
public func remove(token: NSObjectProtocol) {
if let index = tokens.index(where: { $0.isEqual(token) }) {
tokens.remove(at: index)
}
notificationCenter.removeObserver(token)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment