Skip to content

Instantly share code, notes, and snippets.

@danielt1263
Last active May 15, 2020 14:23
Show Gist options
  • Select an option

  • Save danielt1263/0a71423c578f2bf3b15c to your computer and use it in GitHub Desktop.

Select an option

Save danielt1263/0a71423c578f2bf3b15c to your computer and use it in GitHub Desktop.
Swift replacement for KVO
//
// 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