Skip to content

Instantly share code, notes, and snippets.

@53ningen
Last active April 12, 2016 14:28
Show Gist options
  • Save 53ningen/8c31ffaafbd57086de563e598d5f2706 to your computer and use it in GitHub Desktop.
Save 53ningen/8c31ffaafbd57086de563e598d5f2706 to your computer and use it in GitHub Desktop.
import Swift
import Foundation
let observable = BehaviorSubject(value: "cocoa")
let observer = AnyObserver<String> {
switch $0 {
case .Next(let str): NSLog(str)
default: break
}
}
let disposable = observable.subscribe(observer) // observer が observable の購読を開始
observable.on(.Next("chino")) //=> NSLog("chino")
observable.on(.Next("maya")) //=> NSLog("maya")
observable.on(.Next("megu")) //=> NSLog("megu")
disposable.dispose() // 購読を解除
observable.on(.Next("tippy")) //=> もう NSLog されない
let obj1 = NSObject()
let obj2 = NSObject()
unsafeAddressOf(obj1) == unsafeAddressOf(obj1) //=> true
unsafeAddressOf(obj1) == unsafeAddressOf(obj2) //=> false
extension BehaviorSubject: ObserverType {
public typealias E = Element
public func on(event: Event<Element>) {
switch event {
case .Next(let value):
self.value = value
default:
break
}
observers.forEach { $0.on(event) }
}
}
public final class BehaviorSubject<Element>: Observable<Element> {
private var value: Element
public init(value: Element) {
self.value = value
}
private var observers = [AnyObserver<Element>]()
public override func subscribe<O : ObserverType where O.E == E>(observer: O) -> Disposable {
let obs = AnyObserver(observer: observer)
observers.append(obs)
return SubscriptionDisposable(owner: self, key: unsafeAddressOf(obs))
}
func unsubscribe(key: UnsafePointer<Void>) {
observers = observers.filter { unsafeAddressOf($0) != key }
}
}
public struct SubscriptionDisposable<T>: Disposable {
private weak var owner: BehaviorSubject<T>?
private let key: UnsafePointer<Void>
public init(owner: BehaviorSubject<T>, key: UnsafePointer<Void>) {
self.owner = owner
self.key = key
}
public func dispose() {
owner?.unsubscribe(key)
}
}
public class NopDisposable: Disposable {
private init() {}
public static let instance = NopDisposable()
public func dispose() {}
}
public enum Event<Element> {
case Next(Element)
case Error(ErrorType)
case Completed
}
extension Event {
public var isStopEvent: Bool {
switch self {
case .Next: return false
case .Error, .Completed: return true
}
}
}
public protocol ObserverType {
associatedtype E
// 通知を受ける口
func on(event: Event<E>)
}
public protocol ObservableType {
associatedtype E
// 通知先を登録する口
func subscribe<O: ObserverType where O.E == E>(observer: O) -> Disposable
}
public protocol Disposable {
func dispose()
}
public class AnyObserver<Element>: ObserverType {
public typealias E = Element
public typealias EventHandler = Event<E> -> Void
private let eventHandler: EventHandler
public init(eventHandler: EventHandler) {
self.eventHandler = eventHandler
}
public init<O: ObserverType where O.E == Element>(observer: O) {
self.eventHandler = observer.on
}
public func on(event: Event<E>) {
eventHandler(event)
}
}
public class Observable<Element>: ObservableType {
public typealias E = Element
public func subscribe<O : ObserverType where O.E == E>(observer: O) -> Disposable {
abstractMethod()
}
}
/// 抽象メソッドを表現するための苦肉の策
@noreturn func abstractMethod() -> Void {
fatalError("abstract method")
}
// String値を状態として持つ、Observable(観測可能な)値
let observable = Variable("cocoa")
// Observable<String> に状態遷移に対して、何かアクションを行いたい観測者
let observer = AnyObserver<String>{
// 具体的なアクションをここで定める
switch $0 {
case .Next(let str): NSLog(str)
default: break
}
}
// observer が observable の観測を開始する(観測を終了するためのオブジェクトが返る)
let disposable = observable.asObservable().subscribe(observer)
// observable に状態遷移を発生させる => NSLog("chino") が実行される
observable.value = "chino"
disposable.dispose() //=> 観測を終了する
observable.value = "tippy" //=> observableの状態遷移時にもうなにも起こらない
func setNumber(number: Int) {
lock.lock()
self.number = number
lock.unlock()
}
func setNumber(number: Int) {
lock.lock(); defer { lock.unlock() }
self.number = number
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment