spin-example-reactiveswift.swift

March 15, 2020 ยท View on GitHub

// the State of the feedback loop struct Levels { let left: Int let right: Int }

// the transition requests of the feedback loop enum Event { case increaseLeft case decreaseLeft case increaseRight case decreaseRight }

// the side effects of the feedback loop func leftEffect(inputLevels: Levels) -> SignalProducer<Event, Never> { // this is the stop condition to our Spin guard inputLevels.left != inputLevels.right else { return .empty }

// this is the regulation for the left level
if inputLevels.left < inputLevels.right {
    return SignalProducer(value: .increaseLeft)
}  else {
    return SignalProducer(value: .decreaseLeft)
}

}

func rightEffect(inputLevels: Levels) -> SignalProducer<Event, Never> { // this is the stop condition to our Spin guard inputLevels.left != inputLevels.right else { return .empty }

// this is the regulation for the right level
if inputLevels.right < inputLevels.left {
    return SignalProducer(value: .increaseRight)
}  else {
    return SignalProducer(value: .decreaseRight)
}

}

// the reducer of the feedback loop func levelsReducer(currentLevels: Levels, event: Event) -> Levels {

guard currentLevels.left != currentLevels.right else { return currentLevels }

switch event {
    case .decreaseLeft:
        return Levels(left: currentLevels.left-1, right: currentLevels.right)
    case .increaseLeft:
        return Levels(left: currentLevels.left+1, right: currentLevels.right)
    case .decreaseRight:
        return Levels(left: currentLevels.left, right: currentLevels.right-1)
    case .increaseRight:
        return Levels(left: currentLevels.left, right: currentLevels.right+1)
}

}

// The builder way to build the Spin let levelsSpin = Spinner .initialState(Levels(left: 10, right: 20)) .feedback(Feedback(effect: leftEffect)) .feedback(Feedback(effect: rightEffect)) .reducer(Reducer(levelsReducer))

// The declarative way to build the Spin let levelsSpin = ReactiveSpin(initialState: Levels(left: 10, right: 20), reducer: Reducer(levelsReducer)) { Feedback(effect: leftEffect) Feedback(effect: rightEffect) }

// to make a reactive stream from the Spin SignalProducer.stream(from: levelsSpin)