Created
January 22, 2018 07:36
-
-
Save morpheby/f4d0e56ff0d2a6e41c6e195f247d5c63 to your computer and use it in GitHub Desktop.
This file contains 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
// Example usage: | |
// class A { | |
// lazy var event = Observable(self) | |
// ... | |
// func doSomeStuff() { | |
// ... | |
// event.fire() | |
// } | |
// } | |
// class B { | |
// let a: A | |
// init(a: A) { | |
// self.a = a | |
// a.event.observe(observer: self) { selfInBlock, a in | |
// ... | |
// } | |
// } | |
// } | |
import Foundation | |
struct ObservationInfo<T: AnyObject, U: AnyObject> { | |
weak var observer: T? | |
unowned let observable: Observable<U> | |
} | |
typealias ObservationCaller = () -> Bool | |
/** Provides capability to add alien observers with their own observation context | |
* Usage: | |
* Create instance lazy variable (that would be observation container) and assign to it value | |
* Observable(##your_class##). That would do. To fire just call .fire on the variable. | |
* To add observer use observe function and pass the observation variable | |
* as observable. | |
*/ | |
public class Observable<T: AnyObject> { | |
public typealias Observant = T | |
fileprivate var callers: [ObservationCaller] = [] | |
weak var observantWeak: Observant? | |
public var observant: Observant { | |
get { | |
return observantWeak! | |
} | |
set { | |
observantWeak = newValue | |
} | |
} | |
public init(_ observant: Observant) { | |
self.observant = observant | |
} | |
func append(caller: @escaping ObservationCaller) { | |
self.callers.append(caller) | |
} | |
public func fire() { | |
self.callers = self.callers.filter { c -> Bool in return c() } | |
} | |
} | |
extension Observable { | |
public func observe<A: AnyObject> (observer: A, fire: @escaping (A, Observant) -> ()) { | |
let info = ObservationInfo(observer: observer, observable: self) | |
let caller: ObservationCaller = { | |
if let observer = info.observer { | |
fire(observer, info.observable.observant) | |
return true | |
} else { | |
// Apparently, no more observer | |
return false | |
} | |
} | |
callers.append(caller) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment