RxSwift — その概要、機能、リアクティブプログラミング

著者: IT Sectr 公開日: 2026-05-03 読了時間: 10 分

RxSwiftは、iOS向けのリアクティブプログラミングライブラリで、Observableパターンと関数型オペレーターを実装し、非同期データストリームを扱います。ReactiveX(Rx)の概念をSwift言語に移植し、UI、ネットワークリクエスト、データベース、タイマーからのイベントを処理するための統一APIを提供します。ReactiveX、2025によると、このライブラリはGitHub上の6万以上のプロジェクトで使用されており、ネイティブCombineが登場するまではSwiftにおけるリアクティブプログラミングの標準であり続けています。RxSwiftは、デリゲート、クロージャ、通知を単一のイベント処理チェーンに置き換えます。

重要なポイント

  • RxSwift — Observableパターンとオペレーターチェーンに基づくSwift向けReactiveX実装
  • Observable — 成功、エラー、または無限に完了できる非同期イベントのソース
  • Subject — ObservableとObserverのハイブリッドで、手動でストリームにイベントを送信できる
  • Schedulers は、購読、監視、イベント処理を実行するスレッドを制御する
  • オペレーター map、flatMap、filter、combineLatestは、競合状態なしでストリームを変換・結合する

RxSwiftとは?

RxSwiftは、Microsoftが2012年に.NET向けに作成したReactiveX(Rx)ライブラリのSwiftポートです。Rxの核となる考え方は、あらゆる非同期データソースをObservableシーケンスとして表現し、関数型オペレーターを適用できるようにすることです。iOS開発では、RxSwiftはUIイベント(ボタンタップ、テキスト入力、ジェスチャー)を、明示的なデリゲートやtarget-actionなしでアプリケーションロジックにバインドするために使用されます。

ライブラリは3つのモジュールで構成されています:RxSwift(コア — Observable、Operator、Scheduler)、RxCocoa(UIKit統合 — UIButton、UITextField、UITableView用のrx拡張)、RxRelay(終端イベントなしのSubject)。この分離により、コアをサーバーサイドSwiftやテストで使用し、UIラッパーはiOSアプリケーションにのみ接続できます。

Stack Overflow、2025の調査によると、RxSwiftはiOS向けのサードパーティライブラリでトップ5に入ります。その人気の主な理由は、すべての非同期パターンの統一的な処理にあります:URLSessionによるネットワークリクエスト、UIViewPropertyAnimatorによるアニメーション、NotificationCenterによる通知、DelegateProxyによるデリゲート — これらすべてが予測可能なライフサイクルを持つObservableに集約されます。

リアクティブプログラミングの哲学

リアクティブプログラミングは、プログラムがデータの変更をポーリングするのではなく、それに反応するパラダイムです。「データを取得→処理→UIを更新」と書く代わりに、開発者は変換チェーンを記述します:「データが変わったら、フィルターを適用し、次にmap、そしてUIを更新する」。RxSwiftは、遅延実行を伴うObservableチェーンを通じてこのパラダイムを実装します — 購読者が現れるまでは何も起こりません。

RxSwiftの主要コンポーネント:Observable、Subject、Disposable

ObservableはRxSwiftの基本的な型で、時間経過に伴うイベントのシーケンスを表します。Observableは3種類のイベントを送信できます:next(新しい値)、error(ストリームを終了するエラー)、completed(正常完了)。有限Observable(すべての値を送信後に完了)と無限Observable(例:UIイベント — 決して完了しない)があります。

Observableとそのライフサイクル

Observableのライフサイクルには3つの段階があります:作成(create、just、from)、変換(オペレーターmap、filter、flatMap)、購読(subscribe)。購読がない場合、Observableは何も実行しません — これは遅延シーケンスです。購読後、Observableは完了するか、購読者がDisposableを介して購読を解除するまで、購読者にイベントを送信し始めます。

swift
import RxSwift

// 配列からObservableを作成
let numbers = Observable.from([1, 2, 3, 4, 5])

// オペレーターによる変換
let squared = numbers
    .filter { $0 % 2 == 0 }
    .map { $0 * $0 }

// イベント処理付き購読
let disposable = squared
    .subscribe(onNext: { print($0) },
               onError: { print("Error: \($0)") },
               onCompleted: { print("Done") })

Subjectは、Observable(購読可能)でもありObserver(イベントを送信可能)でもある型です。RxSwiftは4種類のSubjectを提供します:PublishSubject(新しいイベントのみ)、BehaviorSubject(初期値付き)、ReplaySubject(直近N件のイベントをバッファリング)、AsyncSubject(完了前の最後の値のみ)。Subjectは、命令型コード(クロージャ、デリゲート)をリアクティブチェーンに統合するのに便利です。

Disposableは購読解除トークンです。購読者がイベントを受信したくなくなった場合、disposable.dispose()を呼び出します。実際には、DisposeBagが使用されます:所有者(例:UIViewController)の初期化解除時にすべての購読を自動的に解除するDisposableのコレクションです。これにより、手動購読管理で避けられないメモリリークを防ぎます。

Subjectの種類初期値購読者に再送信使用例
PublishSubjectなし新しいイベントのみUIイベント、稀な通知
BehaviorSubjectあり最新+新規状態、データストリーム
ReplaySubjectなしバッファN+新規履歴キャッシュ
AsyncSubjectなし最後のみ計算タスク
PublishRelayなし新規のみエラー/完了なし

ストリーム変換・フィルタリングオペレーター

RxSwiftのオペレーターは、1つのObservableを受け取り、データストリームを変換して別のObservableを返す関数です。オペレーターを組み合わせることで、開発者は中間変数や競合状態なしに宣言的な処理チェーンを構築します。すべてのオペレーターは遅延実行されます:チェーンは記述時に構築され、購読時に実行されます。

変換オペレーターはストリーム内の各イベントを変更します。mapは各要素に関数を適用し、flatMapは各要素からのObservableを単一の平坦なストリームに展開し、scanは中間結果を蓄積します(reduceと似ていますが、各ステップを出力します)。bufferは要素を時間または数でグループ化し、windowはストリームをウィンドウごとにネストされたObservableに分割します。

swift
// オペレーターチェーンの例:debounceを使用した検索
searchTextField.rx.text
    .orEmpty
    .debounce(.milliseconds(300), scheduler: MainScheduler.instance)
    .distinctUntilChanged()
    .flatMapLatest { query -> Observable<[String]> in
        return apiService.search(query)
    }
    .bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, item, cell in
        cell.textLabel?.text = item
    }
    .disposed(by: disposeBag)

フィルタリングオペレーターは、条件を満たすイベントのみを通過させます。filterは述語でフィルタリングし、distinctUntilChangedは前回と異なる値のみを通過させ、takeとtakeWhileはイベント数を制限します。skipskipWhileは最初のN個のイベントまたは条件が満たされるまでのイベントをスキップします。エラー処理には、catchError(インターセプトして代替)とretry(エラー時にシーケンスを再試行)が使用されます。

結合オペレーターは複数のObservableを1つに結合します。combineLatestは複数のストリームからの最新値をタプルにマージし、zipは同じインデックスを持つ要素をペアにし、mergeはイベント到着順に複数のストリームを1つに結合します。withLatestFromはメインストリームからのイベントを別のストリームからの最新値と結合します — 現在の状態を持つUIイベントに便利です。

カテゴリオペレーター説明
変換map各値を関数で変換する
変換flatMapネストされたObservableを平坦なストリームに展開する
フィルタリングfilter述語で値をフィルタリングする
フィルタリングdistinctUntilChanged変更された値のみを通過させる
結合combineLatest2つ以上のストリームからの最新値を結合する
結合zipインデックスで要素をペアにする
制御debounceストリームの停止までイベントを遅延する
制御take最初のN個のイベントを取得しストリームを完了する

Schedulersとスレッド管理

RxSwiftのSchedulerは、実行スレッド(またはキュー)の抽象化です。Schedulerは、イベントの作成、変換、購読がどのスレッドで実行されるかを決定します。開発者が明示的にDispatchQueueを指定するGCDとは異なり、RxSwiftは2つのパラメータを使用します:subscribeOn(どのスレッドでObservableが実行されるか)とobserveOn(どのスレッドで購読者が呼び出されるか)です。

MainSchedulerとBackgroundScheduler

MainSchedulerはメインスレッドでコードを実行します — UIKitの更新に必須です(すべてのUI変更はメインスレッドで行われる必要があります)。SerialDispatchQueueSchedulerはシリアルGCDキューをラップし、ConcurrentDispatchQueueSchedulerは並行キューをラップします。バックグラウンドタスクには、qos: .backgroundまたは.utilityを指定したConcurrentDispatchQueueSchedulerが使用されます。

swift
// 典型的なパターン:バックグラウンド処理+mainでUI
apiService.fetchData()
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { data in
        self.tableView.reloadData()
        self.loadingIndicator.stopAnimating()
    })
    .disposed(by: disposeBag)

Schedulerを適切に使用することで、ネットワークリクエストや負荷の高い計算中のUIブロッキングを防ぎます。subscribeOnは上流全体に影響します(observeOnより前のすべてのオペレーターは指定されたスケジューラーで実行されます)。observeOnは下流を切り替えます — observeOnより後のすべてのオペレーターは指定されたスケジューラーで実行されます。チェーン内には、異なる変換段階でスレッドを切り替えるために複数のobserveOnを配置できます。

SerialDispatchQueueSchedulerはイベントの順次処理を保証し、共有リソースのスレッドセーフティにとって重要です。高負荷の操作(画像処理、JSONパース)にはConcurrentDispatchQueueSchedulerを使用してください — RxSwiftは1つのObservable内ではイベントの順序を保持しますが、異なるObservableは並行して処理される可能性があります。

iOSでのRxSwiftの実践的応用

RxSwiftはiOSプロジェクトで、リアクティブチェーンを介してUIをデータにバインドするために最も頻繁に使用されます。RxCocoaはすべての標準的なUIKitコンポーネントにrx拡張を提供します:UIButton用のrx.tap、UITextField用のrx.text、UIPickerView用のrx.selectedRow。これにより、@IBActionとデリゲートを放棄し、宣言的な購読に置き換えることができます。

MVVMとのRxSwift

MVVM(Model-View-ViewModel)は、ViewModelが状態とビジネスロジックを管理し、ViewがViewModelのリアクティブプロパティを購読するアーキテクチャパターンです。RxSwiftはMVVMに完全に適合します:ViewModelはデータ用のObservableまたはDriverを公開し、Viewはbindを介してそれらを購読します。ViewModelはViewへの参照を持ちません — Viewが消費するObservableを返します。

swift
class LoginViewModel {
    let email = BehaviorRelay<String>(value: "")
    let password = BehaviorRelay<String>(value: "")

    var isFormValid: Observable<Bool> {
        return Observable
            .combineLatest(email, password) {
                !$0.isEmpty && $0.contains("@") && $1.count >= 6
            }
    }
}

// ViewController内:
viewModel.isFormValid
    .bind(to: loginButton.rx.isEnabled)
    .disposed(by: disposeBag)

ネットワークリクエストは、RxSwiftの2番目に一般的なユースケースです。URLSession.rx.responseはHTTPリクエストをObservableにラップし、成功時には(response、data)を、失敗時にはerrorを返します。Codableとmapオペレーターを組み合わせることで、コンパクトなリアクティブAPIレイヤーが得られます:コールバックや各メソッドでのエラー処理なしのObservable<MyModel>。ネットワークエラー時には、retry(3)オペレーターが指数バックオフ付きで自動的に3回リクエストを再試行します。

RxSwift vs Combine

Combineは、iOS 13で導入されたAppleのネイティブフレームワークです。RxSwiftと同じタスクを解決します:Publisher、Subscriber、オペレーターを介した非同期イベントの処理です。ただし、Combineには重要な違いがあります:Failure型による厳格なエラータイピング、Swift Concurrency(async/await)の組み込みサポート、@PublishedとObservableObjectを介したSwiftUIとの統合です。

RxSwiftは後方互換性で優れています — iOS 8+をサポートする一方、CombineはiOS 13+が必要です。RxSwiftはサードパーティ拡張(RxDataSources、RxGesture、RxAnimated)の豊かなエコシステムと詳細なオペレータードキュメントを持っています。古いiOSバージョンをサポートするプロジェクトでは、RxSwiftが唯一の選択肢であり続けています。

iOS 13+の新規プロジェクトでは、AppleはCombineを推奨しています。SwiftUIと緊密に統合され、バイナリサイズが小さく、公式サポートがあります。ただし、既存のRxSwiftコードをCombineに移行するには、すべてのObservable→Publisherを書き換える必要があり、RxCocoaのエコシステムには完全なCombine相当物がありません — UIKitにはすべてのUIコンポーネント用のネイティブPublisherはありません。

特徴RxSwiftCombine
最小iOSiOS 8+iOS 13+
エラータイプError(任意)Generic Failure
UI拡張RxCocoa(UIKit、AppKit)@Published(SwiftUI)
オペレーター400+オペレーター約100オペレーター
Swift Concurrencyブリッジ経由ネイティブサポート
ステータスサードパーティApple公式

よくある質問

RxSwiftのObservableとSubjectの違いは?

Observableは遅延実行によるイベントソースです。SubjectはObservableでありObserverでもあります — 購読して手動で新しいイベントを送信できます。Subjectは、命令型コードをリアクティブチェーンに統合するのに便利です。

CombineではなくRxSwiftを使うべき時は?

RxSwiftは、iOS 11-12のサポートが必要な場合、既存のRxSwiftコードベースがある場合、または豊富なオペレーターエコシステム(Combineの約100に対して400+)が必要な場合に選択されます。iOS 13+の新規プロジェクトではCombineが推奨されます。

DisposeBagとは何ですか?なぜ必要なのですか?

DisposeBagはDisposableトークンのコレクションで、所有者の初期化解除時に自動的にすべての購読を解除します。DisposeBagがないと、購読によってクロージャへの強参照が作成され、UIViewControllerが破棄される際にメモリリークが発生します。

RxSwiftでのエラー処理方法は?

エラーをデフォルト値に置き換えるにはcatchError、Observableの実行を再試行するにはretry、エラーをイベントに変換するにはmaterializeを使用します。UIレイヤーでは、DriverとSignalはエラーを渡しません — 内部で処理されます。

RxCocoaでDriverとObservableの違いは?

Driverは、MainSchedulerでの実行、エラーの不在、リソース共有を保証する特別なObservable型です。DriverはUI更新がメインスレッドで行われることを保証します。Observableはそのような保証を提供しません — observeOnが必要です。

まとめ

  • RxSwiftは、Observableパターンと400以上の変換オペレーターを実装するiOS向けリアクティブプログラミングライブラリ
  • Observable、Subject、Disposableは、すべてのリアクティブチェーンの基礎を形成する3つの基本型
  • オペレーター map、flatMap、filter、combineLatest、debounceは、競合状態なしで宣言的チェーンを構築できる
  • Schedulers(subscribeOn / observeOn)は実行スレッドを管理し、UIブロッキングを防止する
  • RxCocoaはUIKit用のrx拡張を提供し、デリゲートとtarget-actionをリアクティブ購読に置き換える
  • CombineはiOS 13+向けのAppleネイティブ代替だが、RxSwiftは古いバージョンで依然として重要

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください