Skip to content

Instantly share code, notes, and snippets.

@mikeash
Created November 26, 2014 19:09
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 mikeash/2d851492e86736b62779 to your computer and use it in GitHub Desktop.
Save mikeash/2d851492e86736b62779 to your computer and use it in GitHub Desktop.
class ObserverSetEntry<Parameters> {
weak var object: AnyObject?
let f: AnyObject -> Parameters -> Void
init(object: AnyObject, f: AnyObject -> Parameters -> Void) {
self.object = object
self.f = f
}
}
class ObserverSet<Parameters> {
var entries = [ObserverSetEntry<Parameters>]()
func observe<T: AnyObject>(object: T, _ f: T -> Parameters -> Void) -> ObserverSetEntry<Parameters> {
let entry = ObserverSetEntry<Parameters>(object: object, f: { f($0 as T) })
entries.append(entry)
return entry
}
func observe(f: Parameters -> Void) -> ObserverSetEntry<Parameters> {
return self.observe(self, { _ = $0; return f })
}
func removeObserver(entry: AnyObject) {
entries = entries.filter{ $0 !== entry }
}
func notify(parameters: Parameters) {
for entry in entries {
if let object: AnyObject = entry.object {
entry.f(object)(parameters)
}
}
entries = entries.filter{ $0.object != nil }
}
}
class TestObservee {
let stringObservers = ObserverSet<String>()
let twoStringObservers = ObserverSet<(String, String)>()
let intObservers = ObserverSet<(Int, Int)>()
let intAndStringObservers = ObserverSet<(Int, String)>()
func testNotify() {
stringObservers.notify("Sup")
twoStringObservers.notify("hello", "world")
intObservers.notify(42, 43)
intAndStringObservers.notify(42, "hello")
}
}
class TestObserver {
init(observee: TestObservee) {
observee.stringObservers.observe(self, TestObserver.stringChanged)
observee.twoStringObservers.observe(self, TestObserver.twoStringChanged)
observee.intObservers.observe(self, TestObserver.intChanged)
observee.intAndStringObservers.observe(self, TestObserver.intAndStringChanged)
}
deinit {
println("deinit!!!!")
}
func stringChanged(s: String) {
println("stringChanged: " + s)
}
func twoStringChanged(s1: String, s2: String) {
println("twoStringChanged: \(s1) \(s2)")
}
func intChanged(i: Int, j: Int) {
println("intChanged: \(i) \(j)")
}
func intAndStringChanged(i: Int, s: String) {
println("intAndStringChanged: \(i) \(s)")
}
}
let observee = TestObservee()
var obj: TestObserver? = TestObserver(observee: observee)
let token = observee.intAndStringObservers.observe{ println("int and string closure: \($0) \($1)") }
observee.testNotify()
obj = nil
observee.testNotify()
observee.intAndStringObservers.removeObserver(token)
observee.testNotify()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment