A simple and predictable state management library inspired by Flux + Elm + Redux.

Overview

Flywheel

Maven Central GitHub License Kotlin badge-android badge-jvm badge-apple badge-js badge-linux badge-windows badge-native

A simple and predictable state management library inspired by Flux + Elm + Redux. Flywheel is built on top of Corotuines using the concepts of structured concurrency. At the core, lies the State Machine which is based on actor model.

Why Flywheel?

The goal was to make the state management concept of Redux simple, understandable & easy to use in Kotlin based projects. To achieve that, we adapted only the core concepts from Redux and slightly modified them. We excluded Android, Apple or any platform-specific dependencies. It is just pure Kotlin. By doing so, you are free to choose your architecture that best suits your codebase, no need to make any big refactor to fit in Flywheel. Don't be fooled by its simplicity, Flywheel got you covered for all practical use-cases. Even if we missed anything, it can be easily extended to support your use cases.

Getting started

In Kotlin Multiplatfrom project:

kotlin {
  sourceSets {
      val commonMain by getting {
          dependencies {
              implementation("com.msabhi:flywheel:1.1.4-RC")
          }
      }
  }
}

In Android / Gradle project:

dependencies {

    implementation("com.msabhi:flywheel-android:1.1.4-RC")
}

In Apple platforms

You can use CocoaPods to install Flywheel by adding it to your Podfile:

use_frameworks!

target 'MyApp' do

    pod 'Flywheel', '~> 1.1.4-RC'

end

You can use the Swift Package Manager to install Flywheel by adding the proper description to your Package.swift file:

// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "YOUR_PROJECT_NAME",
    dependencies: [
        .package(url: "https://github.com/abhimuktheeswarar/Flywheel.git", from: "1.1.4-RC"),
    ]
)

Then run swift build whenever you get prepared.

Usage

This is how a simple counter example looks like.

  1. Define a state.

    data class CounterState(val counter: Int = 0) : State
  2. Define actions that can change the state.

    sealed interface CounterAction : Action {
    
        object IncrementAction : CounterAction
    
        object DecrementAction : CounterAction
    }
  3. Define a reducer that updates the state based on the action & current state.

    val reduce = reducerForAction<CounterAction, CounterState> { action, state ->
        with(state) {
            when (action) {
                is CounterAction.IncrementAction -> copy(counter = counter + 1)
                is CounterAction.DecrementAction -> copy(counter = counter - 1)
            }
        }
    }
  4. Create a StateReserve.

    val stateReserve = StateReserve(
        initialState = InitialState.set(CounterState()),
        reduce = reduce)
  5. Listen for state changes

    stateReserve.states.collect { state -> println(state.counter) }
  6. Send actions to StateReserve to update the state.

    stateReserve.dispatch(IncrementAction)

To learn more about Flywheel, head on over to our wiki.

License

Copyright (C) 2021 Abhi Muktheeswarar

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
You might also like...
A simple example of the VIPER architecture for iOS apps

Counter Counter is a simple app showing the basics of the VIPER architecture, a version of Uncle Bob’s Clean Architecture for iOS apps. Counter shows

Modern thread-safe and type-safe key-value observing for Swift and Objective-C

Now Archived and Forked PMKVObserver will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork o

Define and chain Closures with Inputs and Outputs

Closure Define and chain Closures with Inputs and Outputs Examples No Scoped State let noStateCount = ClosureString, String { text in String(repea

Write great asynchronous code in Swift using futures and promises

BrightFutures How do you leverage the power of Swift to write great asynchronous code? BrightFutures is our answer. BrightFutures implements proven fu

SwiftUI-compatible framework for building browser apps with WebAssembly and native apps for other platforms
SwiftUI-compatible framework for building browser apps with WebAssembly and native apps for other platforms

SwiftUI-compatible framework for building browser apps with WebAssembly At the moment Tokamak implements a very basic subset of SwiftUI. Its DOM rende

SwiftUI-compatible framework for building browser apps with WebAssembly and native apps for other platforms
SwiftUI-compatible framework for building browser apps with WebAssembly and native apps for other platforms

SwiftUI-compatible framework for building browser apps with WebAssembly At the moment Tokamak implements a very basic subset of SwiftUI. Its DOM rende

Interactive notification pop-over (aka
Interactive notification pop-over (aka "Toast) modeled after the iOS AirPods and Apple Pencil indicator.

Interactive notification pop-over (aka "Toast) modeled after the iOS AirPods and Apple Pencil indicator. Installation The recommended way is to use Co

🤖 RxSwift + State Machine, inspired by Redux and Elm.
🤖 RxSwift + State Machine, inspired by Redux and Elm.

RxAutomaton RxSwift port of ReactiveAutomaton (State Machine). Terminology Whenever the word "signal" or "(signal) producer" appears (derived from Rea

Redux for Swift - a predictable state container for Swift apps

Merge / deprecation announcement: ReduxKit and Swift-Flow have joined forces! The result is ReSwift. The nitty gritty: We decided to deprecate ReduxKi

Unidirectional State Management Architecture for Swift - Inspired by Vuex and Flux
Unidirectional State Management Architecture for Swift - Inspired by Vuex and Flux

Unidirectional State Management Architecture for Swift - Inspired by Vuex and Flux Introduction VueFlux is the architecture to manage state with unidi

Predictable state management for SwiftUI applications.
Predictable state management for SwiftUI applications.

SwiftDux Predictable state management for SwiftUI applications. SwiftDux is a state container inspired by Redux and built on top of Combine and SwiftU

SwiftUI Todo app example using a React/Redux monolithic state store with flux like dispatch/reduce actions
SwiftUI Todo app example using a React/Redux monolithic state store with flux like dispatch/reduce actions

SwiftUI-Todo-Redux SwiftUI Todo Redux app example using a React/Redux monolithic state store with flux like dispatch/reduce actions Background SwiftUI

Elm-parcel-capacitor - A sample setup to build an app with Elm, Capacitor, Parcel and Tailwind CSS

Elm, Capacitor, Parcel and Tailwindcss This project is a sample setup to build a

🌾 Harvest: Apple's Combine.framework + State Machine, inspired by Elm.
🌾 Harvest: Apple's Combine.framework + State Machine, inspired by Elm.

NOTE: This repository has been discontinued in favor of Actomaton. 🌾 Harvest Apple's Combine.framework (from iOS 13) + State Machine, inspired by Elm

VueFlux is the architecture to manage state with unidirectional data flow for Swift, inspired by Vuex and Flux.
VueFlux is the architecture to manage state with unidirectional data flow for Swift, inspired by Vuex and Flux.

Unidirectional State Management Architecture for Swift - Inspired by Vuex and Flux Introduction VueFlux is the architecture to manage state with unidi

Predictable state container for Swift too

ReduxSwift ReduxSwift is a minimal Swift port of Redux, a popular JavaScript library for application state management. Functionality Centralized State

SwiftUI & Combine app using MovieDB API. With a custom Flux (Redux) implementation.
SwiftUI & Combine app using MovieDB API. With a custom Flux (Redux) implementation.

MovieSwiftUI MovieSwiftUI is an application that uses the MovieDB API and is built with SwiftUI. It demos some SwiftUI (& Combine) concepts. The goal

MVVM + FLUX iOS Instagram client  in Swift, eliminates Massive View Controller in unidirectional event/state flow manner
MVVM + FLUX iOS Instagram client in Swift, eliminates Massive View Controller in unidirectional event/state flow manner

CZInstagram MVVM + FLUX iOS Instagram client in Swift, eliminates Massive View Controller in unidirectional event/state flow manner. Unidirectional Da

🚀Comprehensive Redux library for SwiftUI, ensures State consistency across Stores with type-safe pub/sub pattern.
🚀Comprehensive Redux library for SwiftUI, ensures State consistency across Stores with type-safe pub/sub pattern.

🚀Comprehensive Redux library for SwiftUI, ensures State consistency across Stores with type-safe pub/sub pattern.

Comments
  • How would you unit test Actions/Side Effects

    How would you unit test Actions/Side Effects

    Love the library! Great work. I really like the structure and design of it. I am, however, struggling to write unite tests for some code I wrote using this library. Most likely it's just a lack of understanding on my part, but I seem to keep running into deadlock issues when running tests. I'm using the new coroutine test library for testing common code. How would you go about testing SideEffects or Actions in this library?

    opened by alexwhb 0
  • Could not cast value of type '' to 'SharedKotlinx_coroutines_coreFlowCollector'

    Could not cast value of type '' to 'SharedKotlinx_coroutines_coreFlowCollector'

    Hi,

    I am trying to implement a very simple State in my KMM project and I run into an exception. I don't know if I am doing things correctly, here are some details.

    versions

    • kotlin : 1.5.30
    • flywheel : 1.1.4-RC
    • kotlinxCoroutines : 1.5.2-native-mt

    use case

    I would like to State defined in the shared kotlin code base and I would like to collect this State in my Swift view model.

    On Kotlin side

    • I made an State and corresponding Actions in shared (my state has a boolean value modified by the actions)
    • I have SDK kotlin class where I have put a Reducer and a StateReserve

    Now on Swift side :

    • I have imported flywheel framework and the CoroutinesHelper.swift file
    • I have defined the following state in a ViewModel :
    final class MyViewModel: ObservableObject {
        let sdk: MySDK
    
        @Published var myState: MyState = MyState(myBoolean = false)
    
        init() {
            sdk = MySDK()
            sdk.myStateReserve.states.collect(collector: Collector<MyState> { myState in
                self.myState = myState
            } as! Kotlinx_coroutines_coreFlowCollector) { (unit, error) in
                // code executed if the Flow object is completed
            }
        }
    
        ..
    }
    

    what is happening

    So the first thing different from the sample code you provided is that I am forced to cast Collector<MyState> to Kotlinx_coroutines_coreFlowCollector

    And surely the problem is here as the Exception is the following, calling init():

    Could not cast value of type '_TtGC6iosApp9CollectorCSo18SharedMyState_' (0x11046c4d0) to 'SharedKotlinx_coroutines_coreFlowCollector' (0x10218ae48).
    

    Am I doing the most simple thing to collect a state in Swift ? If not I am interested to know how I can improve my code ! Thank you so much !

    (BTW wiki documentation is great !)

    opened by Benoye 1
Releases(v.1.1.5-RC)
Owner
Abhi Muktheeswarar
Jack of all stacks, master of Android.
Abhi Muktheeswarar
VueFlux is the architecture to manage state with unidirectional data flow for Swift, inspired by Vuex and Flux.

Unidirectional State Management Architecture for Swift - Inspired by Vuex and Flux Introduction VueFlux is the architecture to manage state with unidi

Ryo Aoyama 324 Dec 17, 2022
A New, Modern Reactive State Management Library for Swift and SwiftUI (The iOS implementation of Recoil)

RecoilSwift RecoilSwift is a lightweight & reactive swift state management library. RecoilSwift is a SwiftUI implementation of recoil.js which powered

Holly Li 160 Dec 25, 2022
Tempura - A holistic approach to iOS development, inspired by Redux and MVVM

Tempura is a holistic approach to iOS development, it borrows concepts from Redux (through Katana) and MVVM. ?? Installation Requirements CocoaPods ??

Bending Spoons 692 Dec 17, 2022
Swift Apps in a Swoosh! A modern framework for creating iOS apps, inspired by Redux.

Katana is a modern Swift framework for writing iOS applications' business logic that are testable and easy to reason about. Katana is strongly inspire

Bending Spoons 2.2k Jan 1, 2023
ReSwift is a Redux-like implementation of the unidirectional data flow architecture in Swift.

ReSwift is a Redux-like implementation of the unidirectional data flow architecture in Swift. ReSwift helps you to separate three important concerns of your app's components.

null 7.3k Jan 9, 2023
RxReduce is a lightweight framework that ease the implementation of a state container pattern in a Reactive Programming compliant way.

About Architecture concerns RxReduce Installation The key principles How to use RxReduce Tools and dependencies Travis CI Frameworks Platform Licence

RxSwift Community 125 Jan 29, 2022
Very simple Observable and Publisher implementation for iOS apps.

Very simple Observable and Publisher implementation for iOS apps.

Igor Kulman 7 Jun 11, 2022
A Swift based Future/Promises Library for IOS and OS X.

FutureKit for Swift A Swift based Future/Promises Library for IOS and OS X. Note - The latest FutureKit is works 3.0 For Swift 2.x compatibility use v

null 759 Dec 2, 2022
A library for reactive and unidirectional Swift applications

ReactorKit is a framework for a reactive and unidirectional Swift application architecture. This repository introduces the basic concept of ReactorKit

ReactorKit 2.5k Dec 28, 2022
A micro-library for creating and observing events.

Signals Signals is a library for creating and observing events. It replaces delegates, actions and NSNotificationCenter with something much more power

Tuomas Artman 454 Dec 21, 2022