Skip to content

Guide · Open source

How to use RxSwift: install, Observables and operators

Updated · written with AI from the project's own documentation and checked against our catalogue data

RxSwift is an MIT-licensed Swift implementation of Reactive Extensions (Rx). It wraps asynchronous work such as network responses, UI events and value changes in Observable sequences that you subscribe to and transform with operators. This guide covers how to install it, how the core pieces fit together, and how to write a small search flow and bind its results to a table view.

RxSwiftReactiveX/RxSwift · ★ 24.6k · MIT

Quick start

  1. 1Pick an install method. Choose Carthage, SwiftPM, xcframeworks or the manual workspace. Check the SR-12303 note if you plan to use Swift Package Manager.
  2. 2Add the dependency. For Carthage, add github "ReactiveX/RxSwift" "6.10.0" to your Cartfile and run carthage update.
  3. 3Import RxSwift and RxCocoa. Add RxSwift and RxCocoa to your target so you can use Observables and UI bindings.
  4. 4Turn an event into an Observable. Wrap a UI event or a network call with rx extensions, such as searchBar.rx.text.
  5. 5Transform with operators. Chain operators like throttle, distinctUntilChanged and flatMapLatest to shape the stream.
  6. 6Bind to UI and dispose. Use bind(to:) for UI elements and store subscriptions in a DisposeBag.

What RxSwift does and which components you need

Rx is a generic abstraction of computation expressed through the Observable<Element> interface. You broadcast and subscribe to values and other events from an Observable stream. KVO observation, async operations and UI events are all unified under this sequence abstraction.

RxSwift has five components. RxSwift is the core and has no other dependencies. RxCocoa adds Cocoa-specific capabilities such as Shared Sequences and Traits. RxRelay provides PublishRelay, BehaviorRelay and ReplayRelay. RxTest and RxBlocking provide testing capabilities.

  • RxSwift: the core Rx standard, no other dependencies
  • RxCocoa: iOS, macOS, watchOS and tvOS helpers; depends on RxSwift and RxRelay
  • RxRelay: PublishRelay, BehaviorRelay, ReplayRelay; depends on RxSwift
  • RxTest and RxBlocking: testing support; depend on RxSwift

Install RxSwift with Carthage, Swift Package Manager or xcframeworks

The README lists these supported options: manual (open Rx.xcworkspace and run the RxExample target), XCFrameworks, Carthage and Swift Package Manager. RxSwift has no external dependencies. Each release starting with RxSwift 6 includes xcframework binaries.

For Carthage, add the dependency line to your Cartfile and then update. Carthage builds RxSwift as a dynamic library by default. The README also describes a script to build a static library, which you should only use if you need that setup.

For Swift Package Manager, the README says to create a Package.swift file. It also flags a critical cross-dependency bug (SR-12303) that has no upstream answer yet, so check the linked workaround if you use SwiftPM.

  • Carthage: add the dependency to Cartfile, then update
  • XCFrameworks: drag the framework binaries into Frameworks, Libraries, and Embedded Content under your target's General tab
  • Swift Package Manager: create Package.swift; read the SR-12303 note first
  • Manual: open Rx.xcworkspace and run RxExample
github "ReactiveX/RxSwift" "6.10.0" $ carthage update

Create an Observable and subscribe to it

An Observable emits values over time. You subscribe to receive them, and you use operators such as throttle, distinctUntilChanged and flatMapLatest to shape the stream before it reaches your code.

The README example chains these operators on a search bar's text. The throttle waits 300 milliseconds before passing on a value, distinctUntilChanged drops repeated queries, and flatMapLatest switches to the newest search request. Empty queries return an empty list, and errors are replaced with an empty list by catchAndReturn.

  • throttle: limits how often values pass through
  • distinctUntilChanged: skips a value identical to the previous one
  • flatMapLatest: uses only the result of the most recent inner Observable
  • observe(on:): chooses the scheduler for downstream work
let searchResults = searchBar.rx.text.orEmpty .throttle(.milliseconds(300), scheduler: MainScheduler.instance) .distinctUntilChanged() .flatMapLatest { query -> Observable<[Repository]> in if query.isEmpty { return .just([]) } return searchGitHub(query) .catchAndReturn([]) } .observe(on: MainScheduler.instance)

Bind results to a table view

Once you have an Observable of results, you can bind it to UI. The README binds the search results to a table view's items, setting each cell's text from the repository data.

The subscription is tied to a dispose bag. The disposed(by:) call keeps the subscription alive for as long as the bag exists and cleans it up afterward, so store the bag in a property on your view controller.

searchResults .bind(to: tableView.rx.items(cellIdentifier: "Cell")) { (index, repository: Repository, cell) in cell.textLabel?.text = repository.name cell.detailTextLabel?.text = repository.url } .disposed(by: disposeBag)

Test asynchronous code with RxTest and RxBlocking

The README lists testing as a use case, pointing to RxTest and RxBlocking as the tools for Rx-based systems. Both depend on RxSwift. The project's UnitTests documentation covers how to write these tests, and the Tips documentation lists common errors.

  • Read the UnitTests guide in the RxSwift Documentation folder
  • Check Tips.md for common errors

Know when RxSwift is the wrong choice

The README describes Rx as a larger abstraction to learn. If your app only makes simple one-off async calls, basic async/await or Combine may be simpler. The README also compares RxSwift with Combine and ReactiveSwift in a separate comparison document.

  • Simple one-off async calls: async/await or Combine may be enough
  • Need the latest Swift tooling with no caveats: review the SR-12303 Swift Package Manager note

What people use it for

  • Live search that waits for typing to pause before calling a GitHub-style API, as in the README example
  • Binding text fields, table views and other UI elements to data streams
  • Combining network responses and UI events into a single stream
  • Writing unit tests for asynchronous code with RxTest or RxBlocking

Frequently asked questions

Is RxSwift free to use?

RxSwift is released under the MIT licence, as listed on its project page. The MIT licence permits use under its terms, so check the LICENSE file in the repository for the full text.

How do I install RxSwift?

The README lists Carthage, Swift Package Manager, XCFrameworks and a manual workspace option. For Carthage, add github "ReactiveX/RxSwift" "6.10.0" to your Cartfile and run carthage update.

What are the requirements for RxSwift?

The README lists Xcode or a Swift toolchain with Swift Package Manager, Carthage, or manual xcframework setup. It supports iOS, macOS, tvOS, watchOS and Linux, according to its platform badge.

Is RxSwift better than Combine?

The README says Rx is a larger abstraction to learn and that Combine may be simpler for basic async work. RxSwift offers operators and UI bindings with RxCocoa. The project links a separate comparison document with Combine and ReactiveSwift.

Why does Swift Package Manager show problems with RxSwift?

The README notes a critical cross-dependency bug affecting many projects, filed as SR-12303 in early 2020 with no answer yet. It links a partial workaround in the RxSwift issues list.

Where can I get help with RxSwift?

The README links a Slack channel for discussion, an issue template for bug reports, a feature request template and a contribution guide.

New agent skills, repos and AI tools — every week

The best new skills and open-source projects, the fastest-growing repos, and one free prompt. Five minutes to read. Unsubscribe anytime.

Our verdict

RxSwift suits Swift developers building Apple-platform apps who already juggle many asynchronous events, especially when they want to bind UI to data streams or test async code with RxTest and RxBlocking. If you only need simple one-off async calls, basic async/await or Combine is likely the better fit. Check the SR-12303 Swift Package Manager note before committing to SwiftPM.

Install options & downloads