Swiftpack.co - kzlekk/AsyncDispatcher as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
kzlekk/AsyncDispatcher
Simplified Dispatcher implementation of Flux pattern written in Swift using new async/await concurrency model
.package(url: "https://github.com/kzlekk/AsyncDispatcher.git", from: "1.0.1")

AsyncDispatcher

License Language Coverage Status

AsyncDispatcher is a lightweight Dispatcher implementation of Flux pattern.

Dispatcher protocol provides methods and properties allowing to control data flow by sending and handling actions serially but still executing them asynchronously using async/await pattern if needed. Dispatcher is intended to use for state management of business logic components. It can be used as higher level model for UI components in some cases, but not designed to be a view model replacement. Current Dispatcher design is based on the experience from building couple of commercial and personal projects, and efforts of simplifying state management code and trying not to dictate state container implementation too much.

Installation

Swift Package Manager

Add "AsyncDispatcher" dependency via integrated Swift Package Manager in XCode

Usage

Dispatcher is just a protocol, so it does not define strictly, how the state management machine should be look like, and can be adopted to nearly any class.

Example of store object conforming to Dispatcher protocol:


    class CounterStore: Dispatcher {
       
        var pipeline = Pipeline()
        var middlewares = [] as Array<Middleware>
        var isDispatching = false
        
        // The state
        var count: Int = 0
    }
    

State management of the Dispatcher is done via dispatching well known actions. Each action implements its own logic how the for dispatcher's state should be modified.

Example Action implementation which is tied to the CounterDispatcher from the example above:


    extension CounterStore {
     
        struct Increment: Action {
        
            let value: Int = 1
        
            func execute(with store: CounterStore) async {
                store.value += value
            }
        }
    }
    

It is possible to execute actions from another action allowing to make action composition:


    extension CounterStore {
     
        struct IncrementByThree: Action {
            func execute(with store: CounterStore) async {
                await store.execute(Increment())
                await store.execute(Increment())
                await store.execute(Increment())
            }
        }
    }
    

To change the state of the CounterStore from the examples above, we need to dispatch supported action:

    
    let counterStore = CounterStore()
    
    async let one = counterStore.dispatch(CounterStore.Increment())
    async let ten = counterStore.dispatch(CounterStore.Increment(value: 10))
    
    await [one, ten]
    
    print(counterStore.count) // Should print: 11
    

If there is a possibility to use some sort of dependency injection, we can simplify action dispatching code even more:


    protocol CounterStoreAction where Dispatcher == CounterStore {}
    
    extension CounterStoreAction {
        @MainActor func dispatch() {
            await Dependencies.default.counterStore.dispatch(self)
        }
        
        func dispatch() {
            Task { @MainActor in
                await Dependencies.default.counterStore.dispatch(self)
            }
        }
    }
    
    extension CounterStore {     
        struct IncrementByOne: CounterStoreAction {
            func execute(with store: CounterStore) async {
                store.value += 1
            }
        }
    }
    
    // Dispatches the action to singleton store to be executed the main thread. 
    // This way it can be safely dispatched from any point in the code.
    CounterStore.IncrementByOne().dispatch()


GitHub

link
Stars: 4
Last commit: 1 week ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Submit a free job ad (while I'm testing this). The analytics numbers for this website are here.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics