Skip to content

Instantly share code, notes, and snippets.

@JimRoepcke
Created March 26, 2020 01:59
Show Gist options
  • Select an option

  • Save JimRoepcke/9c21b8f438172dcdcafb4aaaef6bf846 to your computer and use it in GitHub Desktop.

Select an option

Save JimRoepcke/9c21b8f438172dcdcafb4aaaef6bf846 to your computer and use it in GitHub Desktop.

Revisions

  1. JimRoepcke created this gist Mar 26, 2020.
    111 changes: 111 additions & 0 deletions Playground.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,111 @@
    /*
    In Xcode 11.3.1, the output is:

    >>> setting n to -1
    sending value through valueDidChange publisher
    situation negative("hello")
    <<< done
    >>> setting n to 1
    sending value through valueDidChange publisher
    situation positive("hello")
    <<< done
    >>> setting n to 1
    sending value through valueDidChange publisher
    situation positive("hello")
    <<< done
    >>> setting n to 0
    sending value through valueDidChange publisher
    situation zero
    <<< done

    In Xcode 11.4, the output is:

    >>> setting n to -1
    <<< done
    >>> setting n to 1
    <<< done
    >>> setting n to 1
    <<< done
    >>> setting n to 0
    <<< done

    */

    import Foundation
    import Combine

    enum Situation {
    case positive(String)
    case zero
    case negative(String)
    }

    struct Thing {
    var n: Int
    var s: String

    var situation: Situation {
    if n > 0 {
    return .positive(s)
    } else if n < 0 {
    return .negative(s)
    }
    return .zero
    }
    }

    public typealias Reducer<Value, Action> = (Value, Action) -> Value

    class Store<Value, Action>: ObservableObject {

    public fileprivate(set) var reducer: Reducer<Value, Action>
    @Published public fileprivate(set) var value: Value {
    didSet {
    print(" sending value through valueDidChange publisher")
    valueDidChange.send(value)
    }
    }

    let valueDidChange = PassthroughSubject<Value, Never>()

    init(initialValue: Value, reducer: @escaping Reducer<Value, Action>) {
    self.reducer = reducer
    self.value = initialValue
    }

    func send(action: Action) {
    self.value = self.reducer(self.value, action)
    }
    }

    let reducer: Reducer<Thing, Int> = { value, action in
    var copy = value
    copy.n += action
    copy.s += "\(action)"
    return copy
    }

    let store = Store<Thing, Int>(
    initialValue: Thing(n: 0, s: "hello"),
    reducer: reducer
    )

    let situationCancellable = store.valueDidChange
    .map(\.situation)
    .sink { situation in print(" situation", situation) }

    print(">>> setting n to -1")
    store.value.n = -1
    print("<<< done")

    print(">>> setting n to 1")
    store.value.n = 1
    print("<<< done")

    print(">>> setting n to 1")
    store.value.n = 1
    print("<<< done")

    print(">>> setting n to 0")
    store.value.n = 0
    print("<<< done")