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.

Revisions

  1. danielt1263 revised this gist Jun 23, 2017. 1 changed file with 35 additions and 32 deletions.
    67 changes: 35 additions & 32 deletions Signal.swift
    Original file line number Diff line number Diff line change
    @@ -17,28 +17,54 @@ public class Signal<T> {
    self.hasValue = false
    self.value = nil
    }

    public init(value: ValueType) {
    self.hasValue = true
    self.value = value
    }

    /// All observers will be notified.
    public func update(value: ValueType) {
    public func update(_ value: ValueType) {
    self.hasValue = true
    self.value = value
    notify(value)
    }

    public func map<U>(transform: (ValueType) -> U) -> Signal<U> {
    /// To observe changes in the signal, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    public func attach(observer: @escaping (ValueType) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(signal: self, function: observer)
    observers.append(wrapped)
    if let value = value, hasValue {
    observer(value)
    }
    return wrapped
    }

    fileprivate func detach(_ wrappedObserver: ObserverWrapper<ValueType>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify(_ value: ValueType) {
    observers.forEach { $0.update(value) }
    }

    private var hasValue: Bool // required for Signal<Void>
    private var value: T?
    private var observers: [ObserverWrapper<T>] = []

    }

    extension Signal {

    public func map<U>(transform: @escaping (ValueType) -> U) -> Signal<U> {
    let result = Signal<U>()
    attach { value in
    result.update(transform(value))
    }
    return result
    }

    public func filter(includeElement: (ValueType) -> Bool) -> Signal<ValueType> {
    public func filter(includeElement: @escaping (ValueType) -> Bool) -> Signal<ValueType> {
    let result = Signal<T>()
    attach { value in
    if includeElement(value) {
    @@ -48,7 +74,7 @@ public class Signal<T> {
    return result
    }

    public func flatMap<U>(transform: (ValueType) -> Signal<U>) -> Signal<U> {
    public func flatMap<U>(transform: @escaping (ValueType) -> Signal<U>) -> Signal<U> {
    let result = Signal<U>()
    attach { value in
    let signal = transform(value)
    @@ -58,45 +84,22 @@ public class Signal<T> {
    }
    return result
    }

    /// To observe changes in the signal, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    public func attach(observer: (value: ValueType) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(signal: self, function: observer)
    observers.append(wrapped)
    if let value = value where hasValue {
    observer(value: value)
    }
    return wrapped
    }

    private func detach(wrappedObserver: ObserverWrapper<ValueType>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify(value: ValueType) {
    observers.forEach { $0.update(value) }
    }

    private var hasValue: Bool // required for Signal<Void>
    private var value: T?
    private var observers: [ObserverWrapper<T>] = []

    }

    private class ObserverWrapper<T>: Disposable {
    init(signal: Signal<T>, function: (value: T) -> Void) {
    init(signal: Signal<T>, function: @escaping (T) -> Void) {
    self.signal = signal
    self.function = function
    }

    func update(value: T) {
    function(value: value)
    func update(_ value: T) {
    function(value)
    }

    func dispose() {
    signal.detach(self)
    }

    unowned let signal: Signal<T>
    let function: (value: T) -> Void
    let function: (T) -> Void
    }
  2. danielt1263 revised this gist Nov 7, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Signal.swift
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    //
    // Subject.swift
    // Signal.swift
    //
    // Created by Daniel Tartaglia on 9/6/15.
    // Copyright © 2016 Daniel Tartaglia. MIT License.
  3. danielt1263 renamed this gist Aug 25, 2016. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  4. danielt1263 revised this gist Aug 21, 2016. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -5,8 +5,6 @@
    // Copyright © 2016 Daniel Tartaglia. MIT License.
    //

    import Swift

    public protocol Disposable {
    func dispose()
    }
  5. danielt1263 revised this gist Aug 21, 2016. 1 changed file with 36 additions and 27 deletions.
    63 changes: 36 additions & 27 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -5,28 +5,52 @@
    // Copyright © 2016 Daniel Tartaglia. MIT License.
    //

    import Swift

    public protocol Disposable {
    func dispose()
    }

    public class Signal<T> {

    typealias ValueType = T
    public typealias ValueType = T

    public init() {
    self.hasValue = false
    self.value = nil
    }

    public init(value: ValueType) {
    self.hasValue = true
    self.value = value
    }

    /// All observers will be notified.
    public func update(value: T) {
    public func update(value: ValueType) {
    self.hasValue = true
    self.value = value
    notify(value)
    }

    public func map<U>(transform: (T) -> U) -> Signal<U> {
    public func map<U>(transform: (ValueType) -> U) -> Signal<U> {
    let result = Signal<U>()
    attach { value in
    result.update(transform(value))
    }
    return result
    }

    public func flatMap<U>(transform: (T) -> Signal<U>) -> Signal<U> {
    public func filter(includeElement: (ValueType) -> Bool) -> Signal<ValueType> {
    let result = Signal<T>()
    attach { value in
    if includeElement(value) {
    result.update(value)
    }
    }
    return result
    }

    public func flatMap<U>(transform: (ValueType) -> Signal<U>) -> Signal<U> {
    let result = Signal<U>()
    attach { value in
    let signal = transform(value)
    @@ -38,44 +62,29 @@ public class Signal<T> {
    }

    /// To observe changes in the signal, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    public func attach(observer: (value: T) -> Void) -> Disposable {
    public func attach(observer: (value: ValueType) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(signal: self, function: observer)
    observers.append(wrapped)
    if let value = value where hasValue {
    observer(value: value)
    }
    return wrapped
    }

    private func detach(wrappedObserver: ObserverWrapper<T>) {
    private func detach(wrappedObserver: ObserverWrapper<ValueType>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify(value: T) {
    private func notify(value: ValueType) {
    observers.forEach { $0.update(value) }
    }

    private var hasValue: Bool // required for Signal<Void>
    private var value: T?
    private var observers: [ObserverWrapper<T>] = []

    }

    public class Subject<T>: Signal<T> {

    public init(value: T) {
    self.value = value
    }

    public override func update(value: T) {
    self.value = value
    super.update(value)
    }

    public override func attach(observer: (value: T) -> Void) -> Disposable {
    let result = super.attach(observer)
    observer(value: value)
    return result
    }

    private var value: T
    }

    private class ObserverWrapper<T>: Disposable {
    init(signal: Signal<T>, function: (value: T) -> Void) {
    self.signal = signal
  6. danielt1263 revised this gist Aug 21, 2016. 1 changed file with 54 additions and 29 deletions.
    83 changes: 54 additions & 29 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -2,69 +2,94 @@
    // Subject.swift
    //
    // Created by Daniel Tartaglia on 9/6/15.
    // Copyright © 2015 Daniel Tartaglia. MIT License.
    // Copyright © 2016 Daniel Tartaglia. MIT License.
    //

    protocol Disposable {
    public protocol Disposable {
    func dispose()
    }

    class Subject<T> {
    public class Signal<T> {

    init(value: T) {
    self.value = value
    typealias ValueType = T

    /// All observers will be notified.
    public func update(value: T) {
    notify(value)
    }

    /// All observers will be notified when the value is set.
    var value: T {
    didSet (oldValue) {
    notify(oldValue)
    public func map<U>(transform: (T) -> U) -> Signal<U> {
    let result = Signal<U>()
    attach { value in
    result.update(transform(value))
    }
    return result
    }

    /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    func attachImmediate(immediate: Bool, observer: (T) -> Void) -> Disposable {
    return attachOldNewImmediate(immediate, observer: { (old, new) -> Void in
    observer(new)
    })
    public func flatMap<U>(transform: (T) -> Signal<U>) -> Signal<U> {
    let result = Signal<U>()
    attach { value in
    let signal = transform(value)
    signal.attach { transformed in
    result.update(transformed)
    }
    }
    return result
    }

    func attachOldNewImmediate(immediate: Bool, observer: (old: T?, new: T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(subject: self, function: observer)
    /// To observe changes in the signal, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    public func attach(observer: (value: T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(signal: self, function: observer)
    observers.append(wrapped)
    if immediate {
    wrapped.update(nil, value)
    }
    return wrapped
    }

    private func detach(wrappedObserver: ObserverWrapper<T>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify(old: T?) {
    observers.forEach { $0.update(old, value) }
    private func notify(value: T) {
    observers.forEach { $0.update(value) }
    }

    private var observers: [ObserverWrapper<T>] = []

    }

    public class Subject<T>: Signal<T> {

    public init(value: T) {
    self.value = value
    }

    public override func update(value: T) {
    self.value = value
    super.update(value)
    }

    public override func attach(observer: (value: T) -> Void) -> Disposable {
    let result = super.attach(observer)
    observer(value: value)
    return result
    }

    private var value: T
    }

    private class ObserverWrapper<T>: Disposable {
    init(subject: Subject<T>, function: (old: T?, new: T) -> Void) {
    self.subject = subject
    init(signal: Signal<T>, function: (value: T) -> Void) {
    self.signal = signal
    self.function = function
    }

    func update(old: T?, _ new: T) {
    function(old: old, new: new)
    func update(value: T) {
    function(value: value)
    }

    func dispose() {
    subject.detach(self)
    signal.detach(self)
    }

    unowned let subject: Subject<T>
    let function: (old: T?, new: T) -> Void

    unowned let signal: Signal<T>
    let function: (value: T) -> Void
    }
  7. danielt1263 revised this gist Nov 14, 2015. 1 changed file with 55 additions and 72 deletions.
    127 changes: 55 additions & 72 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -6,82 +6,65 @@
    //

    protocol Disposable {
    func dispose()
    func dispose()
    }

    class Subject<T> {
    init(value: T) {
    self.value = value
    }
    /// All observers will be notified when the value is set.
    var value: T {
    didSet (oldValue) {
    notify(oldValue)
    }
    }
    /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    func attachImmediate(immediate: Bool, observer: (T) -> Void) -> Disposable {
    return attachOldNewImmediate(immediate, observer: { (old, new) -> Void in
    observer(new)
    })
    }
    func attachOldNewImmediate(immediate: Bool, observer: (old: T?, new: T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(subject: self, function: observer)
    observers.append(wrapped)
    if immediate {
    wrapped.update(nil, value)
    }
    return wrapped
    }
    private func detach(wrappedObserver: ObserverWrapper<T>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }
    private func notify(old: T?) {
    observers.forEach { $0.update(old, value) }
    }
    private var observers: [ObserverWrapper<T>] = []
    init(value: T) {
    self.value = value
    }
    /// All observers will be notified when the value is set.
    var value: T {
    didSet (oldValue) {
    notify(oldValue)
    }
    }
    /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    func attachImmediate(immediate: Bool, observer: (T) -> Void) -> Disposable {
    return attachOldNewImmediate(immediate, observer: { (old, new) -> Void in
    observer(new)
    })
    }
    func attachOldNewImmediate(immediate: Bool, observer: (old: T?, new: T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(subject: self, function: observer)
    observers.append(wrapped)
    if immediate {
    wrapped.update(nil, value)
    }
    return wrapped
    }
    private func detach(wrappedObserver: ObserverWrapper<T>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }
    private func notify(old: T?) {
    observers.forEach { $0.update(old, value) }
    }
    private var observers: [ObserverWrapper<T>] = []
    }

    private class ObserverWrapper<T>: Disposable {
    init(subject: Subject<T>, function: (old: T?, new: T) -> Void) {
    self.subject = subject
    self.function = function
    }
    func update(old: T?, _ new: T) {
    function(old: old, new: new)
    }
    func dispose() {
    subject.detach(self)
    }
    unowned let subject: Subject<T>
    let function: (old: T?, new: T) -> Void
    init(subject: Subject<T>, function: (old: T?, new: T) -> Void) {
    self.subject = subject
    self.function = function
    }
    func update(old: T?, _ new: T) {
    function(old: old, new: new)
    }
    func dispose() {
    subject.detach(self)
    }
    unowned let subject: Subject<T>
    let function: (old: T?, new: T) -> Void
    }

    let x = Subject(value: 11)

    let y = x.attachImmediate(false) { value in
    print("y: \(value)")
    }

    let z = x.attachOldNewImmediate(true) { old, new in
    print("z: old \(old) new \(new)")
    }

    x.value = 7

    z.dispose()

    x.value = 5

  8. danielt1263 revised this gist Nov 14, 2015. 1 changed file with 72 additions and 76 deletions.
    148 changes: 72 additions & 76 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -6,86 +6,82 @@
    //

    protocol Disposable {
    func dispose()
    func dispose()
    }

    class Subject<T> {

    init(value: T) {
    self.value = value
    }

    deinit {
    disposable?.dispose()
    }

    /// All observers will be notified when the value is set through this function.
    func set(value: T) {
    self.value = value
    }

    /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    func attachImmediate(immediate: Bool, observer: (T) -> Void) -> Disposable {
    return attachOldNewImmediate(immediate, observer: { (old, new) -> Void in
    observer(new)
    })
    }

    func attachOldNewImmediate(immediate: Bool, observer: (old: T?, new: T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(subject: self, function: observer)
    observers.append(wrapped)
    if immediate, let value = value {
    wrapped.update(nil, value)
    }
    return wrapped
    }

    func map<U>(transform: (T) -> U) -> Subject<U> {
    let result = Subject<U>()
    result.disposable = self.attachImmediate(true) { [weak result] value in
    result?.value = transform(value)
    }
    return result
    }

    private init() { }

    private func detach(wrappedObserver: ObserverWrapper<T>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify(old: T?) {
    if let value = value {
    observers.forEach { $0.update(old, value) }
    }
    }

    private var value: T? {
    didSet (oldValue) {
    notify(oldValue)
    }
    }

    private var disposable: Disposable?
    private var observers: [ObserverWrapper<T>] = []


    init(value: T) {
    self.value = value
    }

    /// All observers will be notified when the value is set.
    var value: T {
    didSet (oldValue) {
    notify(oldValue)
    }
    }

    /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    func attachImmediate(immediate: Bool, observer: (T) -> Void) -> Disposable {
    return attachOldNewImmediate(immediate, observer: { (old, new) -> Void in
    observer(new)
    })
    }

    func attachOldNewImmediate(immediate: Bool, observer: (old: T?, new: T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(subject: self, function: observer)
    observers.append(wrapped)
    if immediate {
    wrapped.update(nil, value)
    }
    return wrapped
    }

    private func detach(wrappedObserver: ObserverWrapper<T>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify(old: T?) {
    observers.forEach { $0.update(old, value) }
    }

    private var observers: [ObserverWrapper<T>] = []

    }

    private class ObserverWrapper<T>: Disposable {
    init(subject: Subject<T>, function: (old: T?, new: T) -> Void) {
    self.subject = subject
    self.function = function
    }

    func update(old: T?, _ new: T) {
    function(old: old, new: new)
    }

    func dispose() {
    subject.detach(self)
    }

    unowned let subject: Subject<T>
    let function: (old: T?, new: T) -> Void

    init(subject: Subject<T>, function: (old: T?, new: T) -> Void) {
    self.subject = subject
    self.function = function
    }

    func update(old: T?, _ new: T) {
    function(old: old, new: new)
    }

    func dispose() {
    subject.detach(self)
    }

    unowned let subject: Subject<T>
    let function: (old: T?, new: T) -> Void

    }

    let x = Subject(value: 11)

    let y = x.attachImmediate(false) { value in
    print("y: \(value)")
    }

    let z = x.attachOldNewImmediate(true) { old, new in
    print("z: old \(old) new \(new)")
    }

    x.value = 7

    z.dispose()

    x.value = 5

  9. danielt1263 revised this gist Nov 14, 2015. 1 changed file with 17 additions and 12 deletions.
    29 changes: 17 additions & 12 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -26,10 +26,16 @@ class Subject<T> {

    /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    func attachImmediate(immediate: Bool, observer: (T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper(subject: self, function: observer)
    return attachOldNewImmediate(immediate, observer: { (old, new) -> Void in
    observer(new)
    })
    }

    func attachOldNewImmediate(immediate: Bool, observer: (old: T?, new: T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper<T>(subject: self, function: observer)
    observers.append(wrapped)
    if let value = value {
    wrapped.update(value)
    if immediate, let value = value {
    wrapped.update(nil, value)
    }
    return wrapped
    }
    @@ -48,15 +54,15 @@ class Subject<T> {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify() {
    private func notify(old: T?) {
    if let value = value {
    observers.forEach { $0.update(value) }
    observers.forEach { $0.update(old, value) }
    }
    }

    private var value: T? {
    didSet {
    notify()
    didSet (oldValue) {
    notify(oldValue)
    }
    }

    @@ -66,21 +72,20 @@ class Subject<T> {
    }

    private class ObserverWrapper<T>: Disposable {
    init(subject: Subject<T>, function: (T) -> Void) {
    init(subject: Subject<T>, function: (old: T?, new: T) -> Void) {
    self.subject = subject
    self.function = function
    }

    func update(value: T) {
    function(value)
    func update(old: T?, _ new: T) {
    function(old: old, new: new)
    }

    func dispose() {
    subject.detach(self)
    }

    unowned let subject: Subject<T>
    let function: (T) -> Void
    let function: (old: T?, new: T) -> Void

    }

  10. danielt1263 revised this gist Nov 14, 2015. 1 changed file with 18 additions and 11 deletions.
    29 changes: 18 additions & 11 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -11,23 +11,21 @@ protocol Disposable {

    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) {
    init(value: T) {
    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 {
    /// All observers will be notified when the value is set through this function.
    func set(value: T) {
    self.value = value
    }

    /// To observe changes in the subject, attach a block. When you want observation to end, call `dispose` on the returned Disposable.
    func attachImmediate(immediate: Bool, observer: (T) -> Void) -> Disposable {
    let wrapped = ObserverWrapper(subject: self, function: observer)
    observers.append(wrapped)
    if let value = value {
    @@ -38,12 +36,14 @@ class Subject<T> {

    func map<U>(transform: (T) -> U) -> Subject<U> {
    let result = Subject<U>()
    result.disposable = self.attach { [weak result] value in
    result.disposable = self.attachImmediate(true) { [weak result] value in
    result?.value = transform(value)
    }
    return result
    }

    private init() { }

    private func detach(wrappedObserver: ObserverWrapper<T>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }
    @@ -54,6 +54,12 @@ class Subject<T> {
    }
    }

    private var value: T? {
    didSet {
    notify()
    }
    }

    private var disposable: Disposable?
    private var observers: [ObserverWrapper<T>] = []

    @@ -77,3 +83,4 @@ private class ObserverWrapper<T>: Disposable {
    let function: (T) -> Void

    }

  11. danielt1263 revised this gist Nov 14, 2015. 1 changed file with 64 additions and 64 deletions.
    128 changes: 64 additions & 64 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -6,74 +6,74 @@
    //

    protocol Disposable {
    func dispose()
    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>] = []
    /// 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
    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
    }
  12. danielt1263 revised this gist Nov 14, 2015. No changes.
  13. danielt1263 revised this gist Nov 14, 2015. No changes.
  14. danielt1263 revised this gist Nov 14, 2015. 1 changed file with 24 additions and 23 deletions.
    47 changes: 24 additions & 23 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -5,74 +5,75 @@
    // Copyright © 2015 Daniel Tartaglia. MIT License.
    //

    import Foundation

    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?) {
    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 {
    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> = Subject<U>(value: nil)
    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() {
    for observer in observers {
    observer.update(value)
    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) {
    init(subject: Subject<T>, function: (T) -> Void) {
    self.subject = subject
    self.function = function
    }

    func update(value: T?) {
    func update(value: T) {
    function(value)
    }

    func dispose() {
    subject.detach(self)
    }

    unowned let subject: Subject<T>
    let function: (T?) -> Void

    let function: (T) -> Void
    }
  15. danielt1263 revised this gist Oct 22, 2015. 1 changed file with 29 additions and 16 deletions.
    45 changes: 29 additions & 16 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -12,54 +12,67 @@ protocol Disposable {
    }

    class Subject<T> {

    /// The value that is to be observered. All current observers will be notified when it is assigned to.
    var value: T {
    var value: T? {
    didSet {
    notify()
    }
    }
    init(value: T) {

    init(value: T?) {
    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 {
    func attach(observer: (T?) -> Void) -> Disposable {
    let wrapped = ObserverWrapper(subject: self, function: observer)
    observers.append(wrapped)
    return wrapped
    }


    func map<U>(transform: (T?) -> U) -> Subject<U> {
    let result: Subject<U> = Subject<U>(value: nil)
    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() {
    for observer in observers {
    observer.update(value)
    }
    }


    private var disposable: Disposable?
    private var observers: [ObserverWrapper<T>] = []

    }

    private class ObserverWrapper<T>: Disposable {
    init(subject: Subject<T>, function: (T) -> Void) {
    init(subject: Subject<T>, function: (T?) -> Void) {
    self.subject = subject
    self.function = function
    }
    func update(value: T) {

    func update(value: T?) {
    function(value)
    }

    func dispose() {
    subject.detach(self)
    }

    unowned let subject: Subject<T>
    let function: (T) -> Void
    let function: (T?) -> Void

    }
  16. danielt1263 revised this gist Sep 10, 2015. No changes.
  17. danielt1263 revised this gist Sep 10, 2015. No changes.
  18. danielt1263 created this gist Sep 7, 2015.
    65 changes: 65 additions & 0 deletions Subject.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    //
    // Subject.swift
    //
    // Created by Daniel Tartaglia on 9/6/15.
    // Copyright © 2015 Daniel Tartaglia. MIT License.
    //

    import Foundation

    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) {
    self.value = value
    }

    /// 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)
    return wrapped
    }

    private func detach(wrappedObserver: ObserverWrapper<T>) {
    observers = observers.filter { $0 !== wrappedObserver }
    }

    private func notify() {
    for observer in observers {
    observer.update(value)
    }
    }

    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

    }