A super simple library for state management with unidirectional data flow.

Overview

OneWay

Swift release CI license

🚧 OneWay is still experimental. As such, expect things to break and change in the coming months.

OneWay is a super simple library for state management with unidirectional data flow. The original inspiration came from Flux, The Composable Architecture, ReactorKit and many state management libraries. There are no dependencies on third parties like RxSwift, so you can use OneWay purely. It can not only be used in the presentation layer (e.g. with View or ViewController), but can also be used to simplify complex business logic (e.g. while app launching).

Data Flow

flow_description

Usage

Implementing a Way

It is easy to think of a Way as a path through which data passes. You can inherit a Way and should implement as below. It is also freely customizable and encapsulatable, since Way is a class.

final class CounterWay: Way<CounterWay.Action, CounterWay.State> {

    enum Action {
        case increment
        case decrement
        case twice
    }

    struct State: Hashable {
        var number: Int
    }

    override func reduce(state: inout State, action: Action) -> SideWay<Action, Never> {
        switch action {
        case .increment:
            state.number += 1
            return .none
        case .decrement:
            state.number -= 1
            return .none
        case .twice:
            return .concat(
                .just(.increment),
                .just(.increment)
            )
        }
    }
}

Sending Actions

Sending an action to a Way causes changes in the state via reduce().

let way = CounterWay(initialState: .init(number: 0))

way.send(.increment)
way.send(.decrement)
way.send(.twice)

print(way.currentState.number) // 2

Subscribing a Way

When a value changes, it can receive a new value. It guarantees that the same value does not come down consecutively. In general, you don't need to add removeDuplicates().

way.publisher.number
    .sink { number in
        print(number)
    }
    .store(in: &cancellables)

Global States

You can easily subscribe to global states by overriding bind().

let globalTextSubject = PassthroughSubject<String, Never>()
let globalNumberSubject = PassthroughSubject<Int, Never>()

final class CustomWay: Way<CustomWay.Action, CustomWay.State> {
// ...
    override func bind() -> SideWay<Action, Never> {
        return .merge(
            globalTextSubject
                .map({ Action.saveText($0) })
                .eraseToSideWay(),
            globalNumberSubject
                .map({ Action.saveNumber($0) })
                .eraseToSideWay()
        )
    }
// ...
}

Thread Safe or Not

Way has a ThreadOption to consider the multithreaded environment. This option can be passed as an argument to the initializer. Once set, it cannot be changed. In a general environment, it is better to use the default option(current) for better performance. But, if it is initialized with the current option, all interactions (i.e. sending actions) with an instance of Way must be done on the same thread.

let way = TestWay(initialState: initialState, threadOption: .current)
let threadSafeWay = TestWay(initialState: initialState, threadOption: .threadSafe)

Requirements

Minimum Version
Swift 5.5
Xcode 13.0
iOS 13.0

Installation

OneWay is only supported by Swift Package Manager.

To integrate OneWay into your Xcode project using Swift Package Manager, add it to the dependencies value of your Package.swift:

dependencies: [
  .package(url: "https://github.com/DevYeom/OneWay", from: "0.1.0"),
]

License

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

You might also like...
CMPSC475 Final Project, ArboretumID Application allows users to explore the Penn State Arboretum, identify plants and learn about the exhibits!

ArboretumID: CMPSC475 Final Project Taylan Unal (@taylanu) About ArboretumID ArboretumIdentifier (ArboretumID) is an app that enhances the Penn State

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

Elegant state machine for Swift.
Elegant state machine for Swift.

SwiftState Elegant state machine for Swift. Example enum MyState: StateType { case state0, state1, state2 } // setup state machine let machine = S

🌾 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

An experimental time traveling state store for SwiftUI
An experimental time traveling state store for SwiftUI

SwiftUI Time Travel A SwiftUI state store and view that allow you to scrub through an application's state. This is a super rough prototype: it's only

Core Data with ReactiveCocoa

ReactiveCoreData ReactiveCoreData (RCD) is an attempt to bring Core Data into the ReactiveCocoa (RAC) world. Currently has several files with the sour

RxSwift extensions for Core Data

RxCoreData Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Xcode 9.0 Swift 4.0

Two-way data binding framework for iOS. Only one API to learn.

BindKit A simple to use two-way data binding framework for iOS. Only one API to learn. Supports Objective-C, Swift 5, Xcode 10.2, iOS 8 and above. Shi

This Repository holds learning data on Combine Framework

Combine Framework List of Topics Welcome, every section in this repo contains a collection of exercises demonstrating combine's utilization as well as

Comments
  • 1.0.0

    1.0.0

    Added

    • Add async operators in SideWay for async/await
    • Add unit tests for SideWay

    Changed

    • Way adopt ObservableObject
    • Way's State should conform Equatable
    • Rename currentState to state in Way
    opened by DevYeom 0
  • 0.5.0

    0.5.0

    Added

    • A reset() function
      • Reset some properties and subscriptions. This is useful when you need to call bind() again.
    • Benchmark and examples in README.md
    opened by DevYeom 0
Releases(1.2.0)
Owner
SeungYeop Yeom
iOS Developer 🍏
SeungYeop Yeom
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

Ryo Aoyama 324 Dec 17, 2022
Unidirectional Data Flow in Swift - Inspired by Redux

ReSwift Supported Swift Versions: Swift 4.2, 5.x For Swift 3.2 or 4.0 Support use Release 5.0.0 or earlier. For Swift 2.2 Support use Release 2.0.0 or

null 7.3k Dec 25, 2022
🔄 Unidirectional data flow in Swift.

Reactor Reactor is a framework for making more reactive applications inspired by Elm, Redux, and recent work on ReSwift. It's small and simple (just o

Reactor 175 Jul 9, 2022
Unidirectional Data Flow in Swift - Inspired by Redux

ReSwift Supported Swift Versions: Swift 4.2, 5.x For Swift 3.2 or 4.0 Support use Release 5.0.0 or earlier. For Swift 2.2 Support use Release 2.0.0 or

null 7.3k Jan 3, 2023
Unidirectional flow implemented using the latest Swift Generics and Swift Concurrency features.

swift-unidirectional-flow Unidirectional flow implemented using the latest Swift Generics and Swift Concurrency features. struct SearchState: Equatabl

Majid Jabrayilov 104 Dec 26, 2022
🟣 Verge is a very tunable state-management engine on iOS App (UIKit / SwiftUI) and built-in ORM.

Verge.swift ?? An effective state management architecture for iOS - UIKit and also SwiftUI ?? _ An easier way to get unidirectional data flow _ _ Supp

VergeGroup 478 Dec 29, 2022
Super Simple Pager with RxSwift extension

SSPager Super Simple Pager Example To run the example project, clone the repo, and run pod install from the SSPagerExample directory first. Installati

9oya 4 Jul 10, 2022
🤖 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

Yasuhiro Inami 719 Nov 19, 2022
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

Lucas Sunsi Abreu 38 Oct 6, 2020
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