Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,10 @@

* Bumps RxSwift dependency version to 6.x.x (6.9.0 at the time of the release) by @alexvbush
* Adds Swift Package Manager (SPM) setup by @alexvbush
* Improves CocoaPods and Carthage setup by @alexvbush
* Improves CocoaPods and Carthage setup by @alexvbush

### Version 1.1.0

* Adds convenience helpers for interoperating async/await with the RxSwift backbone: `Single.fromAsync` / `Observable.fromAsync` to drop an `async` call into an Rx chain, `Task` lifecycle-cancellation helpers (`cancelOnDeactivate(interactor:)`, `cancelOnStop(_:)`, `cancel(with:)`), and async `Workflow` steps (`onAsyncStep` on the root workflow and on `Step`) (#51)
* Makes Swift Package Manager the canonical build and moves the Carthage Xcode project under `ios/` so it no longer shadows `Package.swift` at the repo root (#55)
* CI: resolves the iOS simulator at runtime instead of pinning a model name (#54), and restricts the workflow token to read-only (#52)
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,52 @@ When you integrate RIBs into your project, it will automatically bring the follo

These dependencies are automatically managed by your chosen package manager and will be resolved to compatible versions.

## async/await Interop with RxSwift

RxSwift is the backbone of RIBs. These are convenience helpers for interoperating with Swift's `async`/`await` from inside the existing Rx lifecycle and workflow model — they let an `async` call drop into an Rx chain, bind a `Task` to a RIB's lifecycle, and add `async` steps to a `Workflow`, all without leaving Rx.

### Calling an async function from an Rx chain

`Single.fromAsync` and `Observable.fromAsync` wrap an `async` call as a cold Rx sequence, so it composes with the operators you already use. The work starts on subscription, and its `Task` is cancelled when the subscription is disposed:

```swift
someObservable
.flatMapLatest { id in
Single.fromAsync { try await service.fetch(id) }
}
.observe(on: MainScheduler.instance)
.subscribe(onNext: { ... })
.disposeOnDeactivate(interactor: self)
```

### Binding a Task to a RIB lifecycle

When you do reach for a bare `Task`, these `Task` helpers cancel it when a RIB scope ends, mirroring the existing `Disposable.disposeOnDeactivate` / `disposeOnStop` / `disposeWith` methods:

```swift
Task { try await work() }.cancelOnDeactivate(interactor: self)
Task { try await work() }.cancelOnStop(worker)
Task { try await work() }.cancel(with: workflow)
```

A `Task` starts running as soon as it's created, so these helpers only cancel it later — they don't delay or prevent it from starting. If the scope is already inactive, the task is cancelled right away.

### Async steps in a Workflow

`onAsyncStep` is a convenience over `onStep` that lets a step's work be `async`, on both the root `Workflow` and any `Step`. Async and Rx steps interleave freely, and the chain still ends in a single `subscribe(...).disposeOnDeactivate(...)`:

```swift
workflow
.onStep { rootItem in rootItem.waitForLogin() } // Rx step
.onAsyncStep { loggedInItem, _ in // async step
(loggedInItem, try await service.fetchClient(id: 42))
}
.onStep { item, client in item.routeToClientDetails(client) }
.commit()
.subscribe(rootActionableItem)
.disposeOnDeactivate(interactor: self)
```

## Related projects

If you like RIBs, check out other related open source projects from our team:
Expand Down
2 changes: 1 addition & 1 deletion RIBs.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'RIBs'
s.version = '1.0.0'
s.version = '1.1.0'
s.summary = 'Uber\'s cross-platform mobile architecture.'
s.description = <<-DESC
RIBs is the cross-platform architecture behind many mobile apps at Uber. This architecture framework is designed for mobile apps with a large number of engineers and nested states.
Expand Down
2 changes: 1 addition & 1 deletion RIBs/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<string>1.1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
Expand Down
Loading