Giter VIP home page Giter VIP logo

swiftui-async-feedback's Introduction

swiftui-async-feedback

Unidirectional Reactive Architecture for SwiftUI. This is a Swift Concurrency implemetation of RxFeedback and CombineFeedback.

Swift Concurrency No custom Views easy Binding
Native-support of async-await and Sendable. No Combine. No custom Views, only use @ViewContext property. Feedback can react the change via Binding that pass to SwiftUI components such as TextField(text: Binding<String>).

Quick Overview

  • Define your System.
    • System is just a namespace of (State, Event, Reducer, [Feedback]).
import AsyncFeedback

struct CounterScreenSystem: SystemProtocol {
    struct State {
        var count: Int = 1
        var message: String? = nil
    }

    enum Event {
        case setMessage(String?)
    }

    // Reducer is a pure function.
    // Reducer will be called when event is triggered.
    //
    // typealias Reducer = (inout State, Event) -> Void
    func reducer() -> Reducer {
        { state, event in
            switch event {
            case .setMessage(let message):
                state.message = message
            }
        }
    }

    // Feedback is a logic to create new Event.
    // Feedback will react state changes.
    func feedbacks() -> [Feedback<Self>] {
        [
            // if State.count is changed, Feedback will react it.
            Feedback(.onChanged(\.count)) { state in
                // if count is multiple of 3, set message.
                if state.count.isMultiple(of: 3) {
                    return .setMessage("multiple of 3!!")
                } else {
                    return .setMessage(nil)
                }
            }
        ]
    }
}
  • just use @ViewContext and start feedback loop by await _context.runFeedbackLoop().
import SwiftUI

struct CounterScreen: View {

    // ViewContext is a propertyWrapper to combine AsyncFeedbacks into SwiftUI.
    @ViewContext(state: CounterScreenSystem.State(), system: CounterScreenSystem())
    var context

    var body: some View {
        VStack {
            Text(context.count.description)
                .font(.largeTitle)

            // easy binding
            // when count will be changed via Binding, Feedback will react it.
            Stepper("", value: $context.count)
                .labelsHidden()

            Text(context.message ?? "")
                .foregroundStyle(.red)
                .font(.largeTitle)
                .frame(height: 30)
        }
        .task {
            // start Feedback loop.
            await _context.runFeedbackLoop()
        }
    }
}

Examples

Counter Todo Paging

Test Support

import XCTest
import AsyncFeedback
import AsyncFeedbackTestSupport

final class CounterScreenSystemTests: XCTestCase {

    @MainActor
    func testWhenCountIsMultipleOf3() async {
        let context = TestContext(
            state: CounterScreenSystem.State(),
            system: CounterScreenSystem()
        )

        await context
            .check { state in
                XCTAssertEqual(state.count, 1)
                XCTAssertNil(state.message)
            }
            .run()
            .do {
                context.eventBinding.count.wrappedValue = 3
            }
            .suspend(while: context.state.message == nil)
            .check { state in
                XCTAssertEqual(state.message, "multiple of 3!!")
            }
            .finish()
    }
}

swiftui-async-feedback's People

Contributors

kntkymt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.