SwiftMVI is an open-source library of conformables and extensions for swift, which provides an ability to build an MVI architecture with independent UseCases
in SwiftUI.
SwiftMVI provides the following features:
- Lightweight & scalable: Wide range of possible implementations from a single reducer to complex feature with child modules.
- Customizable workflows: You can build many variations by conform to
Reducibles
andReducers
. - A simple but very effective API bind parts together, including your existing combine publishers.
- Usable view protocols to implement your own feature driven view.
The main goal is a set of protocols for archiving structured data-flow with minimal effort. But if you familiar with MVI architecture, there are some important differences compared to other MVI implementations:
- a State can be reference or value type. The reducers mutating the actual state via
Processing
, usingstate()
methods, and a reducer always returns Void, if you must to handle an effect useeffect()
method. - On the view side, you can choose between
ObservableObject
orstatePublisher
for updating. - Your existing Combine publishers can be connected using
bind
method to aFeature
, and aFeature
can behave as aPublisher
, when your feature comforms toEventReducer
.
You can use Swift Package Manager to integrate the library by adding the following dependency in your Package.swift file or by adding directly within Xcode:
.package(url: "https://github.com/xtro/SwiftMVI.git", .upToNextMajor(from: "0.2.0"))
Feature:
class CounterFeature: ReducibleState, IntentReducer, Processing {
var state: Int
var statePublisher: StatePublisher
init(state: Int = 0) {
self.state = state
self.statePublisher = .init(state)
}
enum Intent {
case increment
case decrement
}
func reduce(intent: Intent) {
switch intent {
case .increment:
state {
$0 + 1
}
case .decrement:
state {
$0 - 1
}
}
}
}
View:
struct CounterView: FeatureView {
let feature: CounterFeature
func body(_ newState: Int) -> some View {
VStack {
HStack {
Button("−") { feature(.decrement) }
Text("\(newState)")
Button("+") { feature(.increment) }
}
}
}
}
SwiftMVI is an MIT-licensed open-source project with its ongoing development made possible entirely by the support of awesome backers. If you'd like to join them, please consider sponsoring this development.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
This library is released under the MIT license. See LICENSE for details.