LoginSignup
5
5

More than 3 years have passed since last update.

【Swift】RxSwift勉強してみたPart1

Last updated at Posted at 2021-04-02

はじめに

RxSwiftについて学んだことを自分なりにまとめていこうかと思います。

GitHub

用語

Reactive Extensions

オブザーバーパターン、イテレーターパターン、関数型プログラミングの概念を実装したインターフェース。

オブザーバーパターン

プログラミング内にあるオブジェクトのイベントを他のオブジェクトへ通知する処理で使われるデザインパターンの一種。

RxSwift

Reactive Extensionsの概念をSwiftで扱えるようにした拡張ライブラリ。
GitHub

RxCocoa

Reactive Extensionsの概念をUIKitで扱えるようにした拡張ライブラリ。

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

「時間と共に変化する値」と「振る舞い」の関係を宣言的に記述するプログラミングの手法。

ストリーム

時間順に並んだ進行中のイベントのこと
マーブルダイアグラム

RxSwiftの特徴

メリット

値の変化が検知しやすい
非同期処理が簡潔に書ける
時間経過に関する処理をシンプルに書ける
コード全体が一貫する
まとまった流れが見やすい
差分がわかりやすい
処理スレッドを変えやすい
コールバックを減らせる(インデントの浅いコードにできる)

デメリット

学習コストが高い
デバッグしにくい

RxSwiftの導入手法

CocoaPods, Carthage, SwiftPackageManagerなどがある。

RxSwiftの基本的な書き方

以下のように、メソッドチェーンで書くことができます。

loginButton.rx.tap
    .subscribe(onNext: { [weak self] in 
        //処理
})
.disposed(by: disposeBag)

詳細な説明は後述しますが、大まかな流れは以下のようになります。
1.ストリームの購読
2.ストリームにイベントが流れてきた時にどうするかを定義
3.クラスが破棄されると同時に購読を破棄させるように設定

実際に書いてみる

実際に書いたコードはGitHubにあげておきます。今回のコードはSimpleRxSwiftフォルダにあります。

今回以下のようなものをつくってみましょう。
ezgif.com-gif-maker.gif

RxSwiftを使わない場合はこんな感じになると思います。

import UIKit

class SimpleViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func loginButtonDidTapped(_ sender: Any) {
        label.text = "login"
    }

    @IBAction func messageButtonDidTapped(_ sender: Any) {
        label.text = "message"
    }

    @IBAction func logoutButtonDidTapped(_ sender: Any) {
        label.text = "logout"
    }

    @IBAction func backButtonDidTapped(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }

}

このような書き方は、1つのボタンに1つの関数を定義しています。
ボタンが4つなら関数は4つ用意します。

しかし、RxSwiftでは以下のように書きます。

import UIKit
import RxSwift
import RxCocoa

class RxSimpleViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var loginButton: UIButton!
    @IBOutlet weak var messageButton: UIButton!
    @IBOutlet weak var logoutButton: UIButton!
    @IBOutlet weak var backButton: UIButton!
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        loginButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.label.text = "login"
            })
            .disposed(by: disposeBag)

        messageButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.label.text = "message"
            })
            .disposed(by: disposeBag)

        logoutButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.label.text = "logout"
            })
            .disposed(by: disposeBag)

        backButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.dismiss(animated: true, completion: nil)
            })
            .disposed(by: disposeBag)

    }

}

処理は全く同じでが、コードが全然違いますよね。使わない場合と比べて、UIとコードの制約を一つのプロパティの結合で済むようになっているため、緩くできました。

おわりに

次回
RxSwift難しい、、、

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5