Skip to content

Instantly share code, notes, and snippets.

@marty-suzuki
Created June 5, 2018 00:49
Show Gist options
  • Save marty-suzuki/43d576e592ddb9200d6661f5a01b4536 to your computer and use it in GitHub Desktop.
Save marty-suzuki/43d576e592ddb9200d6661f5a01b4536 to your computer and use it in GitHub Desktop.
//: Playground - noun: a place where people can play
import Foundation
// MARK: - Pub / Sub
protocol Subscription {
var id: SubscriptionID { get }
}
struct SubscriptionID: Equatable {
private let rawValue = UUID().uuidString
static func == (lhs: SubscriptionID, rhs: SubscriptionID) -> Bool {
return lhs.rawValue == rhs.rawValue
}
}
enum NotificationService {
private struct _Subscription<T>: Subscription {
let id = SubscriptionID()
let handler: (T) -> ()
}
final class Provider<T> {
private var subscriptions: [_Subscription<T>]
init() {
self.subscriptions = []
}
func publish(_ value: T) {
subscriptions.forEach { $0.handler(value) }
}
func subscribe(_ handler: @escaping (T) -> ()) -> Subscription {
let subscription = _Subscription(handler: handler)
subscriptions.append(subscription)
return subscription
}
func unsubscribe(_ subscription: Subscription) {
subscriptions = subscriptions.filter { $0.id != subscription.id }
}
}
}
do {
let provider = NotificationService.Provider<Int>()
let subscripiton = provider.subscribe {
print("provider: \($0)")
}
provider.publish(1)
provider.publish(2)
provider.unsubscribe(subscripiton)
provider.publish(3)
}
// MARK: - Constant / Variable
final class Variable<T> {
var value: T {
didSet {
provider.publish(value)
}
}
private let provider: NotificationService.Provider<T>
init(_ value: T, provider: NotificationService.Provider<T> = .init()) {
self.value = value
self.provider = provider
}
func subscribe(_ handler: @escaping (T) -> ()) -> Subscription {
handler(value)
return provider.subscribe(handler)
}
func unsubscribe(_ subscription: Subscription) {
provider.unsubscribe(subscription)
}
}
final class Constant<T> {
var value: T {
return variable.value
}
private let variable: Variable<T>
init(_ variable: Variable<T>) {
self.variable = variable
}
func subscribe(_ handler: @escaping (T) -> ()) -> Subscription {
return variable.subscribe(handler)
}
func unsubscribe(_ subscription: Subscription) {
variable.unsubscribe(subscription)
}
}
do {
let variable = Variable<Int>(0)
let subscription1 = variable.subscribe {
print("variable: \($0)")
}
variable.value += 1
variable.value += 1
variable.unsubscribe(subscription1)
variable.value += 1
print("variable.value: \(variable.value)")
let constant = Constant(variable)
let subscription2 = constant.subscribe {
print("constant: \($0)")
}
variable.value += 1
variable.value += 1
constant.unsubscribe(subscription2)
variable.value += 1
print("constant.value: \(constant.value)")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment