SwiftUIBloc

The Bloc Pattern is a way to separate UI and Logic in SwiftUI codes.
The Bloc is like a state machine where it accepts an event and produce a state.

Example

To run the example project, clone this repo, and open iOS Example.xcworkspace from the iOS Example directory.

Requirements

macOS(.v10_15), iOS(.v13), tvOS(.v14), watchOS(.v6)

Installation

Add this to your project using Swift Package Manager. In Xcode that is simply: File > Swift Packages > Add Package Dependency... and you're done. Alternative installations options are shown below for legacy projects.

CocoaPods

If you are already using CocoaPods, just add 'SwiftUIBloc' to your Podfile then run pod install.

Usage

  1. Create Event and State :
enum CounterEvent: EventBase {
    case increase
    case decrease
}
enum CounterState: StateBase {
    case initial
    case counter(Int)
}
  1. Extend Bloc and override mapEventToState and use yield to dispatch states:
final class CounterBloc: Bloc<CounterEvent, CounterState> {
    private var count = 0
    
    override func mapEventToState(_ event: CounterEvent) {
        switch event {
        case .increase:
            count += 1
            yield(.counter(count))
        case .decrease:
            count -= 1
            yield(.counter(count))
        }
    }
}

Bloc Views

You can easily monitor bloc.state in your view's body and show the proper view base on that.
To remove some boilerplate there are couple of views you can use:

BlocBuilderView

BlocBuilderView is a View which requires a Bloc and a @ViewBuilder. BlocBuilderView handles building the view in response to new states.

BlocBuilderView(bloc: bloc) { state in
    // return view based on bloc state
}

You can control when the builder function should be called by providing buildWhen function.

BlocBuilderView(bloc: bloc, buildWhen: {previousState, currentState in
    // return true/false to determine whether or not
    // to rebuild the view with state
}) {
    // return view  based on bloc's state
}

BlocListenerView

BlocListener is a View which takes a bloc and invokes the listener in response to state changes in the bloc.

BlocListenerView(bloc: bloc, listener: {state in
    // do stuff here based on bloc's state
}) {
    // return view
}

You can control when the listener function should be called by providing listenWhen function.

BlocListenerView(bloc: bloc, listener: {state in
    // do stuff here based on bloc's state
}, listenWhen: { (previousState, currentState) -> Bool in
    // return true/false to determine whether or not
    // to call listener with state
}) {
    // return view 
}

Author

Mehdi Sohrabi

GitHub

https://github.com/mehdok/SwiftUIBloc