はじめに
SwiftはObjective-Cに比べて文法がシンプルで、アプリ開発の初学者にとっても取り組みやすい言語です。AppleがiOSアプリ言語としてSwiftを採用した時期からStoryboardの機能も充実し、UIとプログラムを分離した開発もより行いやすくなりました。
ですが、「IBActionやdelegateなどでは動作が起きる場所と処理を定義する場所が離れている」「非同期の処理がイメージしにくい」といった、Objective-C時代からの欠点も残っています。この結果として、Swiftのプログラムが長くなるほど、プログラムが読みにくくなり、メンテナンスも困難になります。また複雑な処理になるほど、処理がUIに依存しがちになるなどの問題も起こります。
これらの問題を解決する手段の1つとしてリアクティブプログラミングの導入が考えられます。連載第1回では、SwiftでのiOSアプリ開発におけるリアクティブプログラミングの導入に関して、基本的な説明を行います。
リアクティブプログラミングの概要と導入
Swiftでリアクティブプログラミングを導入する際に、前提となる知識について簡単に説明します。
命令型プログラミングと宣言型プログラミング
プログラムには命令型プログラミングと宣言型プログラミングという2種類の考え方があります。次の加算の式を例に簡単に両者の違いを考えてみます。
a = b + c;
命令型プログラミングでは、b = 1/c = 2であれば、aの値は3です。「a = b + c」の式が実行された後で、b/cの値が変更されたとしてもaの値は変わりません。Swiftも含め、PHPやJavaなどの一般的なプログラムではこの命令型プログラミングで処理が行われます。
これに対して宣言型プログラミングでは、「aはbとcの和である」という意味を常に持ち続けます。b = 1/c = 2であれば、aの値は3です。その後、b=2/ c=3という具合にb/cの値が変更された際には、aの値はその和である5となります。
このように命令型プログラミング と宣言型プログラミング では式が同じでも処理の意味が異なります。両者の違いをまとめると次のようになります。
種類 | 意味 | 補足 |
---|---|---|
命令型プログラミング | bとcの値でaの値が決まる | 式が実行された後、aの値は変わらない |
宣言型プログラミング | aはbとcの和である | b,cの値が変化すればaの値も変化する |
リアクティブプログラミングを実際に利用する前に、この違いを確認しておいてください。
リアクティブプログラミングとは
リアクティブプログラミングは、宣言型プログラミングにおいて時間軸の概念を特に重視したプログラムの考え方です。プログラム内での値の変化を時間軸で捉え、値が変わった際に発生するイベントによって処理を行います。発生するイベントは、動作によって単発で発生する1回だけのものと違って、時間とともに流れてくるデータのリスト(イベントストリーム)として捉えます。前節で例にあげた「a = b + c」をリアクティブプログラミングの概念で図にまとめると次のようになります。
まず左から右へ推移する時間軸を引きます。その時間軸上で、発生するイベントを○(マーブル)などで表します。このように、時間の経過とイベントストリームの関係を表します。上記のような図をマーブルダイアグラムといいます。
変数b/cの値が変わる際にはイベントが発生するものと考えます。そのタイミングで時間軸上に○を配置します。b/cの値が変わった際に、「a = b + c」の処理が実行され、aの値が変わります。aの値が変わる際も、同様に時間軸上に○を配置します。
「a = b + c」の処理は時間軸上でイベントが発生するたびに実行される非同期なものです。したがってスマートフォンの画面では、処理の開始~終了まで画面上で待ち時間が発生することはありません。図ではイベントが発生する際に式「a = b + c」を実行していますが、もちろん任意の処理を実行することが可能です。
リアクティブプログラミングは、簡単に言えば、時間/イベント/非同期の処理の3つの要素でプログラムを構成するものだといえます。
RxSwiftの利用
具体的にSwiftでリアクティブプログラミングを利用する際に必要となる事柄について簡単に説明します。
Rxとは
マイクロソフトが2009年に、.NET用のリアクティブプログラミングライブラリとしてフレームワーク「Reactive Extensions」を公開しました。Reactive Extensionsは.NET以外の言語にも移植され、オープンソース化を経て「ReactiveX」という名前になりました。現在ではその略称「Rx」が定着し、Rxを移植した各言語はRx○○と呼ばれています。このRxが利用できるSwiftのライブラリがRxSwiftです。RxSwiftには、前節で説明した時間/イベント/非同期の処理を的確に管理できる仕組みが備わっています。
RxSwiftで時間/イベント/非同期の処理を実装する
時間/イベント/非同期を意識した処理は、RxSwiftを使わなくても、Swiftが本来持っている機能だけで実装できます。しかし、Swiftの本来の機能のみでこれらの処理を実装する場合、次の問題が発生します。
- 処理内容をメインスレッドに渡さない限り、UIに反映できないなど非同期特有の面倒な処理が存在する
- 非同期処理の中で不具合が発生した場合、原因の特定が困難
- UIでの非同期処理とAPIの呼び出しやJSONの解析などでは同じ非同期処理でも記述内容が大きく異なる
RxSwiftを導入すると、時間/イベント/非同期の処理を簡潔に宣言できるので、上記のような問題を意識する必要はありません。RxSwiftの仕組みを利用すると、プログラム内で発生するすべてのイベント処理を時間軸上で同じように扱えるとともに、共通したフォーマットで処理を記述することができます。このことは、チームで作業する際にも、各メンバーのソースコードの差異が大きくなりにくいという意味で非常に役立ちます。
RxSwiftのインストール
RxSwiftのインストールは、CocoaPodsを利用して行います。CocoaPodsの使い方に関しては、こちらの記事「Swift 4の外部ライブラリを利用して機能を実装する」で確認できます。
GitHubにある手順に従ってPodfileを作成してインストールします。
# Uncomment the next line to define a global platform for your project # platform :ios, '9.0' target 'RxSwiftSample1' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! # Pods for RxSwiftSample1 pod 'RxSwift', '^> 4.0' pod 'RxCocoa', '^> 4.0' end
ライブラリの名前はRxSwiftですが、インストールする際にはmacOS用のRxフレームワークであるRxCcocoaとセットでインストールします。