Skip to content

xtro/SwiftMVI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SwiftMVI Logo

SwiftMVI

Swift platforms Swift Package Manager compatible GitHub Current version

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.

Overview

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 and Reducers.
  • 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, using state() methods, and a reducer always returns Void, if you must to handle an effect use effect() method.
  • On the view side, you can choose betweenObservableObject or statePublisher for updating.
  • Your existing Combine publishers can be connected using bind method to a Feature, and a Feature can behave as a Publisher, when your feature comforms to EventReducer.

Installation

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"))

Usage

Example

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) }
            }
        }
    }
}

Sponsors

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.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

This library is released under the MIT license. See LICENSE for details.