SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

RxSwiftで一歩進んだiOSアプリ開発

RxSwiftの基本的な仕組みを理解しよう

RxSwiftで一歩進んだiOSアプリ開発 第2回

  • X ポスト
  • このエントリーをはてなブックマークに追加

UIを利用してRxSwiftのサンプルを確認する

 UIを利用する場合は、RxSwift内で各UIをRxで拡張したクラスが用意されています。UIを利用した処理では、これらのクラスのプロパティやメソッドを利用することで、開発者自身がUI単位でObservableオブジェクトを生成する必要はありません。ここではRxSwiftの基本的な動きの例を、UIを利用して確認してみます。実際に画面上でUIを動かすとObserverパターンの使いどころや便利さがより実感できます。

Rxを利用してUIのイベントから処理を動かす/値を取得する

 RxSwiftで用意されている各UIをRxで拡張したクラスでは、次のようにrxプロパティで各UIのイベントを監視できます。

[リスト10]各UIクラスでのRxを経由したイベントへのアクセス
#UIオブジェクト#.rx.#イベント#

 どのようなイベントが利用できるかはUIによって異なるので、詳細はRxSwiftライブラリ内のクラスやドキュメントを参照してみてください。

[リスト11]UISampleViewController.swift
import UIKit
import RxSwift    // -------(1)
import RxCocoa

class UISampleViewController: UIViewController {

    @IBOutlet weak var sampleButton: UIButton!    // -------(2)
    @IBOutlet weak var sampleSwitch: UISwitch!
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        sampleButton.rx.tap.subscribe(    // -------(3)
            onNext: { 
                print( " tap ! " )
            }
        ).disposed(by: disposeBag)

        sampleSwitch.rx.isOn.subscribe(    // -------(4)
            onNext: { bool in
                 print( bool ? " ON " : " OFF " )
            }
        ).disposed(by: disposeBag)
    }

 (1)最初にRxSwift/RxCocoaのライブラリをインポートします。

 (2)次にUIButtonとUISwicthのオブジェクト/DisposeBagオブジェクトを用意します。

 (3)UIButtonオブジェクトのrx.tapプロパティでタップイベントを取得できます。タップイベントをsubscribe(_:)メソッドで監視し、タップイベントが発生した際に「tap !」をコンソールに表示します。

 (4)UISwitchオブジェクトのrx.isOnプロパティでスイッチのOn/Off状態を取得できます。On/Off状態をsubscribe(_:)メソッドで監視し、スイッチを切り替えた際にOnかOffかをコンソールに出力します。

 RxSwiftを利用すると、従来のSwiftと違ってIBOutletで処理を用意する必要はありません。データストリームとしてイベントから流れて来る値を反映した処理を動かす、といった具合に、直感的に処理を記述できるのが特徴です。

delegateの代わりにRxで処理を行う

 SwiftでUIの処理を行う際に必須となるのがdelegateです。delegate自体は、UIに固有の定番の処理を共通のフォーマットで記述できる点で非常に便利です。

 しかし、 delegateをいくつも利用するとソースコードが長くなってしまったり、UIの定義と処理が離れてしまうため処理を追うのが困難になったりと、欠点もあります。RxSwiftでは、本来delegateで行う処理に関してもRxの拡張クラスで内包されており、Observerパターンで記述できます。

 タブバーでアイコンを選択した際に、選択したアイコンのbadgeValueのみを10にする処理をRxSwiftで実装すると次の通りになります。本来ならばUITabBarDelegateで処理すべき内容が、RxSwiftを利用するとシンプルに記述できます。

[リスト12]SampleTabBarViewController.swift
self.tabBar.rx.didSelectItem.subscribe(
    onNext:
    {
        [weak self] tabItem in
            // 最初に全てのアイコンのbadgeValueを空にする
            self?.tabBar.items?.forEach{ $0.badgeValue = nil }
            // 選択したアイコンのbadgeValueを10に
            tabItem.badgeValue = "10"
    }
).disposed(by: disposeBag)
選択したアイコンのbadgeValueのみを10にする
選択したアイコンのbadgeValueのみを10にする

 rx.didSelectItemプロパティは、UITabBarDelegateプロトコルのtabBar(_:didSelect:)メソッドで得られるUITabBarItemオブジェクトを参照できます。rx.didSelectItemプロパティをsubscribe(_:)メソッドで監視することで、タブが選択されたタイミングで任意の処理を行います。UITabBarDelegateプロトコルを利用するよりもシンプルでわかりやすく処理を記述することができます。サンプルのようにクロージャの中からselfでビューコントローラー自身を参照する場合には、weak/unownedで弱参照であることを明記してクロージャで得られる変数の前にselfを記述してください。

データバインドを利用する

 データバインドとは、アプリケーションで利用するデータを画面上のビューなどと結合することを言います。Rxの世界では、画面上に存在するオブジェクトとRxで監視可能なオブジェクトの値を結合し、オブジェクトの値が変化した場合に即座に画面に反映するという処理でよく利用されます。Observableクラスが実装しているObservableTypeプロトコルのbind(_:)メソッドを利用します。

[リスト13]bind(_:)メソッドの書式
#Rxオブジェクト#.bind(to:#Rxオブジェクト#)

 bind(_:)メソッドは結合するRxオブジェクトの型は等しい場合に限り利用可能です。入力欄に入力された文字列とラベルに表示する文字列をbind(_:)メソッドで結合する例は次の通りになります。UILabelには配置した場所がわかるように背景をグレーにしています。

[リスト14]SampleBindViewController.swift
class SampleBindViewController: UIViewController {
    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var label: UILabel!
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.textField.rx.text
            .bind(to:self.label.rx.text)			// bund(_:)メソッドで2つの値を結合
            .disposed(by: disposeBag)		// 解放
    }
データバインドの利用例
データバインドの利用例

 サンプルを実行すると、入力欄に入力した文字列がそのままラベルに表示されます。

 UITextFieldオブジェクトとUILabelオブジェクトのrx.textプロパティをbind(_:)メソッドで繋ぐだけで、リアルタイムに2つのオブジェクトの値を等価にすることが可能であることがわかります。このことをうまく利用すると、例えばUIで入力された値をビューコントローラー内でグローバルに持つ変数の値を結合し、リアルタイムに処理を行うといったことも可能となります。

まとめ

 今回はRxSwiftの基本的な処理であるObserverパターンに関して、基礎的な紹介と簡単な使い方を説明しました。各種UIのrxプロパティで参照できるオブジェクトに関しては、非常に種類が多いので一度RxSwift配布元で確認してみてください。本来のSwiftよりも簡潔な記述で処理を実装できることがわかります。次回はObservable関連クラスに関してもう少し詳しく説明します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
RxSwiftで一歩進んだiOSアプリ開発連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 片渕 彼富(カタフチ カノトミ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/11051 2018/09/12 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング