Swiftpack.co -  nalexn/minimalist as Swift Package
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
nalexn/minimalist
Observable Property and Signal for building data-driven UI without Rx
.package(url: "https://github.com/nalexn/minimalist.git", from: "1.0.1")

Minimalist

Build Status Coverage Status

Building data-driven UI without Rx


I'm a big fan of reactive frameworks. I've used RxSwift, ReactiveSwift, Combine, and I suffer every time I join the project where the team cannot adopt one for some reason.

  • Problem #1: Teams beware the complexity and steep learning curve
  • Problem #2: Traditional frameworks are too bulky for small projects

This library is a take on cutting off everything non-essential. In fact, all you need to build the data-driven UI is observable property and event broadcaster. And that's all that you get with this micro-framework (just 100 lines of code):

@Property

Also known as:

  • BehaviorRelay in RxSwift
  • MutableProperty in ReactiveSwift
  • CurrentValueSubject in Combine
class ViewModel {
    @Property var items: [Items] = []
}

// Access the current value:
viewModel.items.count

// Subscribe on changes of the value:
viewModel.$items.observe(with: self) { (obj, items) in
    ...
}

@Signal

Also known as:

  • PublishRelay in RxSwift
  • Signal in ReactiveSwift
  • PassthroughSubject in Combine
class ViewModel {
    @Signal var didReceiveMessage: Accepts<Message>
}

// Broadcast a notification:
didReceiveMessage.send(message)

// Subscribe on updates:
viewModel.$didReceiveMessage.observe(with: self) { (obj, message) in
    ...
}

Features

Access control

You can restrict the write access from outside of the module using just Swift's access control:

class ViewModel {
    @Property private(set) var value: String = "Minimalist"
    @Signal private(set) var signal: Accepts<Void>
}

// Cannot change property or trigger a signal:
viewModel.value = "abc" // ❌
viewModel.signal.send(()) // ❌

Automatic memory management

Subscription is bound to the lifetime of the supplied object and gets detached automatically. That object is also provided in the callback along with the value, so you don't need to do the [weak self] dance all the time:

class ViewController: UIViewController {
    var tableView: UITableView
    
    func viewDidLoad() {
        ...
        viewModel.$items.observe(with: self) { (vc, items) in
            vc.tableView.reloadData()
        }
    }
}

Filter state updates (Redux)

Data-driven UI works best with unidirectional data flow design, which may involve using a centralized state in the app.

Upon subscription, you can specify the KeyPath to the value inside the state container to receive scoped and filtered updates (like with distinctUntilChanged):

$appState.observe(\.screens.loginScreen, with: self) { (obj, state) in
    ...
}

Pro Tip: \.self is also a valid KeyPath. This way you can discard the same values while observing a primitive type.

Installation

@ Carthage

github "nalexn/minimalist"

@ CocoaPods

pod 'Minimalist'

@ SPM

.package(url: "https://github.com/nalexn/minimalist.git", from: "1.0.0")

blog venmo

GitHub

link
Stars: 78
Last commit: 5 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.

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