SHOEISHA iD

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

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

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

MVVMモデルをもっと便利に使ってみよう(前編)~入力/出力の変数に注目したMVVMモデルの設計

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

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

MVVMモデルをもっとわかりやすく便利に利用する(2)

入出力を重視したRxSwift派生ライブラリ

 RxSwiftには、RxSwift Communityでさまざまな派生ライブラリが開発されています。その中の1つに、入出力に重点を置いたライブラリ「Action」があります。Actionライブラリは、Swiftで行う処理を抽象化し、入力/出力/エラー/処理中の各値をプロパティから得るインターフェースを持ちます。具体的にはActionクラスで処理を定義し、次の4つのプロパティで処理に関する値を指定、参照します。

Actionクラスのプロパティ
名前 概要
inputs
Actionクラスで定義した入力変数
elements Actionクラスで定義した出力変数
errors エラー発生時にエラー情報をAction.Errorで返す
executing 処理中かどうかをtrue/falseで返す

 Actionクラスで処理を定義する際は、第一引数をinputsプロパティで、第二引数をonNextで渡す変数として定義します。

[構文]Actonクラスの書式
let アクション名: Action<入力用の変数の型, 出力用の型> = Action { (入力用の変数) in
            // 処理
            return 出力用の変数
}

 Actionクラスを初期化する際に、先に入出力を行う変数の型を定義します。この時に定義する入出力の変数がそれぞれinputs/elementsプロパティの値となります。

 inputsプロパティに入力変数の値が入った際に、Actionクラスで定義した処理が実行されます。Actionクラスの処理内容はクロージャで定義します。渡されるのは入力用の変数です。クロージャ内の処理を行った後に、出力用の変数を返すように定義します。動作を定義する際には入出力の変数は型だけで定義していますが、利用する際はObservable変数として値の受け渡しを行います。この点に気をつけてください。

 Actionを利用する具体的な例として、IDとパスワードでログインするフォームの処理を、Actionクラスで実装するサンプルを次に示します。

[リスト4]LoginSampleViewController.swift
class LoginSampleViewController: UIViewController {

    @IBOutlet weak var idTextField: UITextField!               // ID入力欄
    @IBOutlet weak var passwordTextField: UITextField!  // パスワード入力欄
    @IBOutlet weak var loginButton: UIButton!                  // ログインボタン
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        // ログインの処理をActionで定義
        // IDとパスワードを入力してログイン処理後に結果をBoolで返す
        let loginAction: Action<(String,String), Bool> = Action {  // ----------------(1)
            (username, password) in
            // ログインが成功したものとしてtrueを返す
            return Observable.just(true)
        }

        // IDとパスワードをObservable化
        let idAndPassword = Observable.combineLatest(idTextField.rx.text.orEmpty,
                                                      passwordTextField.rx.text.orEmpty)  // ----------------(2)

        // ログインボタン押下時にloginActionのinputsにIDとパスワードをbind
        loginButton.rx.tap.asObservable()
            .withLatestFrom(idAndPassword)
            .bind(to: loginAction.inputs)
            .disposed(by: self.disposeBag)  // ----------------(3)

        // loginActionの処理結果を受けてログイン後の処理を行う
        loginAction.elements.subscribe( onNext:{ bool in  // ----------------(4)
                if bool {
                    print("login ok!")
                } else {
                    print("login fail")
                }
            }).disposed(by: self.disposeBag)
    }
# 略

 最初にActionクラスの処理を定義します(1)。入力用の変数はIDとパスワードのString型の変数、戻り値はBool型です。入力だけでなく、処理の後に返す出力用の変数の型も処理の前に指定します。サンプルでは便宜上、常にtrueを返すようにしています。ObservableクラスのcombineLatestメソッドで、IDとパスワードを1つのデータストリームに結合します(2)。

 ログインボタンが押された場合に、(2)のデータストリームがActionクラスのinputsプロバティにデータバインドし、値が渡るようにします(3)。Actionクラスのinputsプロバティに入力用の値が渡った時に、(1)で定義したActionクラスの処理が行われます。Actionクラスの処理が終わり次第、elementsプロパティで処理の結果を得られます(4)。

 Actionクラスのelementsプロパティの値を監視することで、Actionクラスの処理の戻り値の取得とその後の処理を行うことができます。

 サンプルの流れのイメージは次の図の通りです。

ログイン処理をActionクラスで実装する例
ログイン処理をActionクラスで実装する例

 Actionクラスを利用すると、このように処理の過程を監視するのではなく、処理の入力と出力のみを監視することで機能を実装することができます。

今回利用するライブラリ

 今回のサンプルで利用するライブラリは次の通りです。

サンプルで利用するライブラリ
ライブラリ名 概要 
Action RxSwift拡張
RxOptional RxSwiftオペレーター拡張
Kanna HTML解析
AlamofireImage 非同期の画像読み込み

 各ライブラリはCocoaPodsでインストールしてください。

[リスト5]Podfile
target 'RxSample5' do
  use_frameworks!

  # Pods for RxSample5
  pod 'RxSwift'
  pod 'RxCocoa'
  pod 'Action'
  pod 'RxOptional'
  pod 'Kanna'
  pod 'AlamofireImage'
end

 Action以外のライブラリの機能に関してはサンプルとともに説明します。

入出力を重視したクラス構成を考える

 前節で紹介した各ライブラリを利用して、Yahoo!画像検索を利用した画像検索アプリを作成してみます。

作成するアプリの概要

 画面の入力欄に入力したキーワードに基づいてYahoo!画像検索を行います。検索結果を解析して、コレクションビューに検索結果の画像を一覧で表示します。

 検索キーワードが3文字以上で検索可能に/検索中はローディングを表示/エラーが発生した場合はエラー内容をアラートで表示します。このイメージは次の図の通りです。

Yahoo画像検索を利用した画像検索アプリ
Yahoo!画像検索を利用した画像検索アプリ

 Yahoo!画像検索は、APIは提供されていないので、画面のHTMLを解析して画像のURLのみを抽出します。

作成するアプリの各クラス

 作成するサンプルの各クラスは、MVVMモデルに準じて次のように作成します。

サンプルの各クラス
クラス/構造体名 概要 
Img 検索結果を格納
ViewController  入力欄、検索ボタン、コレクションビューを表示
ImageItemCell コレクションビューのセル
SearchViewModel 入出力変数の管理/Actionによる処理の制御

 サンプルでは、Actionライブラリを利用したView-ViewModel間の入出力の変数の管理を目的としています。MVVMモデル内のModelの役割については、簡略化するためにサンプルでは省いています。前回に引き続き、View-ViewModel間の変数のやり取りにはデータバインドを用い、View以外ではUIKitフレームワークをimportしないようにします。

まとめ

 今回はMVVMモデルを利用する上で、入力と出力の変数を区別して変数を定義することを中心に説明しました。これまでは、RxSwiftの使い方に主眼を置いて来ましたが、今回はRxSwiftをどう使うか、という例をあげました。次回は今回のサンプルの続きを作成しながら、入出力の変数を区別して、入力/出力/処理中/エラー発生時の具体的な処理方法について説明します。

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

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

もっと読む

この記事の著者

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

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング