Last active
May 15, 2020 14:23
-
-
Save danielt1263/0a71423c578f2bf3b15c to your computer and use it in GitHub Desktop.
Swift replacement for KVO
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
| // | |
| // Subject.swift | |
| // | |
| // Created by Daniel Tartaglia on 9/6/15. | |
| // Copyright © 2015 Daniel Tartaglia. MIT License. | |
| // | |
| protocol Disposable { | |
| func dispose() | |
| } | |
| class Subject<T> { | |
| /// The value that is to be observered. All current observers will be notified when it is assigned to. | |
| var value: T? { | |
| didSet { | |
| notify() | |
| } | |
| } | |
| init(value: T? = nil) { | |
| self.value = value | |
| } | |
| deinit { | |
| disposable?.dispose() | |
| } | |
| /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable | |
| func attach(observer: (T) -> Void) -> Disposable { | |
| let wrapped = ObserverWrapper(subject: self, function: observer) | |
| observers.append(wrapped) | |
| if let value = value { | |
| wrapped.update(value) | |
| } | |
| return wrapped | |
| } | |
| func map<U>(transform: (T) -> U) -> Subject<U> { | |
| let result = Subject<U>() | |
| result.disposable = self.attach { [weak result] value in | |
| result?.value = transform(value) | |
| } | |
| return result | |
| } | |
| private func detach(wrappedObserver: ObserverWrapper<T>) { | |
| observers = observers.filter { $0 !== wrappedObserver } | |
| } | |
| private func notify() { | |
| if let value = value { | |
| observers.forEach { $0.update(value) } | |
| } | |
| } | |
| private var disposable: Disposable? | |
| private var observers: [ObserverWrapper<T>] = [] | |
| } | |
| private class ObserverWrapper<T>: Disposable { | |
| init(subject: Subject<T>, function: (T) -> Void) { | |
| self.subject = subject | |
| self.function = function | |
| } | |
| func update(value: T) { | |
| function(value) | |
| } | |
| func dispose() { | |
| subject.detach(self) | |
| } | |
| unowned let subject: Subject<T> | |
| let function: (T) -> Void | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment