Swiftpack.co -  maxvol/RaspSwift as Swift Package
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
Reactive Aggregate State Pipeline (based on RxSwift)
.package(url: "https://github.com/maxvol/RaspSwift.git", from: "1.0.4")


NB: refer to rxswift branch for a working version, this branch is under development.

RASP - Reactive Aggregate State Pipeline

This Unidirectonal Data Flow framework is inspired by Redux and built on top op RxSwift framework. Comparing to other similar frameworks, it is exceptionally simple by design and requires the very minimum of boilerplate code.


Rather than declaring plenty of Publish/BehaviorSubjects and grouping them ad hoc by .combineLatest(), on many occasions it makes more sense to group state values together by domain, such as:

  • REST/HATEOAS state with recent links
  • geolocation state
  • UI navigation state
  • lifecycle state
  • motion state
  • data state
  • etc.

That way, at every value update you have a complete snapshot of what is going on in particular domain. Besides, there is only one way to update domain state, namely by sending event to the state aggregator - this ensures consistency of every state snapshot.

alt text

How it works (per domain state):

  • events from different sources are gathered into a single stream with .merge() operator
  • on every event from the combined stream, it gets applied (reduced) to the current state via .scan() operator
  • consumers can subscribe to domain state as a whole or to a single field by using selector which is .map().distinctUntilChanged()

For example, combining independently updated heading and location into one consistent geolocation state snapshot would look as follows -

alt text

...where events and state are defined as follows:

NB this documentation is for v1 using RxSwift, while v2 is using Combine

struct GeoEvent: RaspEvent {
    case heading(heading)
    case location(Location)

struct GeoState: RaspState {
var heading: Heading
    var location: Location

    mutating func apply(event: RaspEvent) {
        switch event {
        case let geoEvent as GeoEvent:
            switch event {
            case .heading(let heading):
                self.heading = heading
            case .location(let location):
                self.location = location

A more generic example of usage:

struct MyRestState: RaspState {
    var links: [String: String] = [:]

    mutating func apply(event: RaspEvent) {
        switch event {
        case let event1 as Event1:
            self.links["\(event1.value)"] = "\(event1.value)"

struct Event1: RaspEvent {
    let value: Int

let scheduler = SerialDispatchQueueScheduler(qos: .default)
let event1 = Observable<Int>.interval(0.3, scheduler: scheduler).take(5).map { value in
    return Event1(value: value)

let scheduler2 = SerialDispatchQueueScheduler(qos: .default)
let event2 = Observable<Int>.interval(0.5, scheduler: scheduler2).take(5).map { value in
    return Event1(value: value)

let myRestAggregator = RaspAggregator<MyRestState>(initial: MyRestState(), sources: event1.asRaspEvent(), event2.asRaspEvent())

myRestAggregator.state.subscribe( onNext: { state in
}).disposed(by: self.disposeBag)

let sel1 = RaspSelector<MyRestState, Int> { state -> Int in
    let value: Int = state.links.count
    return value

let one1 = myRestAggregator.select(selector: sel1)

one1.subscribe( onNext: { field in
}).disposed(by: self.disposeBag)
  • Version



Stars: 4
Last commit: 4 weeks ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Release Notes

SPM support
2 years ago

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API