Revolve

1.0.1

A lightweight, composable architecture for building SwiftUI applications. It is inspired by Redux and uses Combine to manage app state, actions, and reducers.
Handasatic/Revolve

What's New

1.0.1

2023-04-27T15:55:02Z

Initial Release.

Revolve โ†ป

Revolve is a light-weight library for building applications with a robust and composable architecture. It is a Redux-based and leverages the power of the Combine framework to streamline your app's state management and UI development. Designed specifically for SwiftUI, Revolve makes creating efficient, maintainable, and enjoyable applications easier than ever.

What is Revolve?

Revolve is a modern architecture library for SwiftUI apps, which leverages Redux and Combine to manage your app's state, actions, and side effects. The library enables you to build clean and maintainable applications, making it easier to test, scale, and reason about your code.

Features

  • ๐Ÿ“ฆ Swift Package Manager support
  • ๐Ÿ”— Composable reducers and state
  • ๐Ÿ’ช Type-safe actions using enums
  • ๐Ÿงช Easily testable with CombineSchedulers

Installation

Swift Package Manager

Add the following dependency to your Package.swift:

.package(url: "https://github.com/Handasatic/Revolve.git", from: "1.0.0")

Examples

We provide a simple example of how to use Revolve:

  • Basic Example - A simple example demonstrating the core concepts of Revolve.
  • Advanced Example - Coming soon

Infrastructure

Reducers

A Reducer in Revolve is a pure function that takes an inout state and an action and applies the action to the state. It has the following signature:

public typealias Reducer<State: Revolve.State, Action: Revolve.Action> = (inout State, Action) -> Void

Combine

Revolve provides a combine function that allows you to combine multiple reducers into a single reducer. This ensures you can easily compose reducers that handle different parts of the state:

public func combine<State, Action>(
    reducers: Reducer<State, Action>...
) -> Reducer<State, Action> where State: Revolve.State, Action: Revolve.Action {
    return { state, action in
        for reducer in reducers {
            reducer(&state, action)
        }
    }
}

Basic usage

Here's a quick example to get you started with Revolve:

Defining State

Create a struct conforming to Revolve.State to define your app's state. This struct should contain all the necessary properties to represent your app's current state.

struct AppState: Revolve.State {
    var user: UserState
    var settings: SettingsState
}

struct UserState: Revolve.State {
    var name: String
    var age: Int
}

struct SettingsState: Revolve.State {
    var notificationsEnabled: Bool
    var darkModeEnabled: Bool
}

Defining Actions

Define an enum conforming to Revolve.Action to represent the different actions that can be performed in your app. For a more organized codebase, you can group actions by the state they affect.

eenum AppAction: Revolve.Action {
    case user(UserAction)
    case settings(SettingsAction)
}

enum UserAction: Revolve.Action {
    case setName(String)
    case setAge(Int)
}

enum SettingsAction: Revolve.Action {
    case setNotificationsEnabled(Bool)
    case setDarkModeEnabled(Bool)
}

Defining Reducers

Create a reducer function that takes the current state and an action as its arguments and returns an updated state. To handle state composition, you can create separate reducers for each state struct and use a top-level reducer to delegate actions to their respective reducers.

let appReducer: Reducer<AppState, AppAction> = { state, action in
    switch action {
    case let .user(userAction):
        userReducer(state: &state.user, action: userAction)
    case let .settings(settingsAction):
        settingsReducer(state: &state.settings, action: settingsAction)
    }
}

let userReducer: Reducer<UserState, UserAction> = { state, action in
    switch action {
    case let .setName(name):
        state.name = name
    case let .setAge(age):
        state.age = age
    }
}

let settingsReducer: Reducer<SettingsState, SettingsAction> = { state, action in
    switch action {
    case let .setNotificationsEnabled(enabled):
        state.notificationsEnabled = enabled
    case let .setDarkModeEnabled(enabled):
        state.darkModeEnabled = enabled
    }
}

Creating a StateStore

Instantiate a StateStore with the initial state, reducer, and a scheduler.

let store = StateStore(initialState: AppState(user: UserState(name: "", age: 0), 
                                              settings: SettingsState(notificationsEnabled: true, 
                                                                      darkModeEnabled: false)), 
                                    reducer: appReducer, 
                                    scheduler: DispatchQueue.main.eraseToAnyScheduler())

Then, inject the StateStore into your SwiftUI views.

Description

  • Swift Tools 5.8.0
View More Packages from this Author

Dependencies

Last updated: Wed Mar 20 2024 10:51:26 GMT-0900 (Hawaii-Aleutian Daylight Time)