降りつぶし.net~同期するWebアプリ・スマホアプリの開発・運用~

第5回 iPhone用アプリケーション「i降りつぶし」の開発

この記事を読むのに必要な時間:およそ 9 分

乗下車年別画面・乗下車月別画面・乗下車日別画面・駅一覧画面

図8 乗下車年別画面・乗下車月別画面・乗下車日別画面・駅一覧画面

図8 乗下車年別画面・乗下車月別画面・乗下車日別画面・駅一覧画面

乗下車日別の統計を見ることができます。最大4階層構成で,乗下車年を選び,次に月を選び,さらに日を選ぶと,最大4階層めでその日付に乗下車した駅の一覧が表示されます。

この画面の実装上の最大の特異は,階層が4階層固定にならないことです。降りつぶし.netは,乗下車した年月日を年・月・日それぞれのレベルで,あいまいに入力することができます。そのうち,乗下車年不明・年はわかっているが月日不明,という2つのパターンにおいて,階層がそれぞれ減ることになります。また,未乗下車の駅一覧も,最上位階層の次はすぐ駅一覧画面になります。

このため,乗下車年別画面で「年月日不明」⁠未乗下車」⁠月日不明」がタップされた場合を,各セルに対応する日付値第2回2ページ目を見ることで判別し,該当した場合は駅一覧画面を開き,それ以外の場合は1階層低い画面を開く,という実装をしています。

駅一覧画面のソート順は,とくにキーがないため,エンドユーザには意味不明なのですが,駅コード順です。

同期画面

前回解説した,本ソリューション最大のキモである同期機能を,実際に実行する画面です。

図9 初期の同期画面

図9 初期の同期画面

初期状態では,画面には「同期を開始する」というボタンがあるのみです。一方,既に同期機能を利用したことがある場合,ログイン状態が保持されていれば,その他にも「同期日時をクリア」⁠ログアウト」というボタンが表示されています。

実際には,これらのボタンが貼り付けられた全画面のビューと,Webページを表示する全画面のWebビューの2つが重ねられており,状態遷移によっていずれかのみを表示するようになっています。またログイン状態と非ログイン状態でのボタンの表示の差異は,単に各ボタンの表示・非表示を切り換えているだけです。

同期開始ボタンをタップすると,Webアプリに非同期通信でアクセスします。Webアプリ側での動作は第3回2ページに記載されているとおりで,認証済であればテキストでユーザ名を返し,認証されていなければログイン画面をHTMLで返します。i降りつぶしは,ユーザ名を受信できたらそのまま前回解説の同期機能を実行し,ログイン画面を受信した場合はそのHTMLをWebビューに注入して表示を切り換えます。

図10 Webアプリからの認証画面

図10 Webアプリからの認証画面

この表示は,スマホアプリに組み込まれたUIではなく,Webアプリによる同期専用の認証画面のHTMLです。

ここでユーザ名とパスワードを入力し,⁠ログイン」をタップすると,Webアプリの認証が行われます。認証が成功すればボタンのビューに切り換えて同期を実行し,成功しなければふたたびこの画面を表示します。

またこの表示の下部には「Login with Twitter」ボタンがあります。これがタップされた場合,Twitterによる認証画面が表示されます。

図11 Twitterからの認証画面

図11 Twitterからの認証画面

前回説明しました(3ページ)が,このOAuth認証の利用が,同期画面の実装をややこしくしています。

このTwitterの画面には「Twitterに登録する」「プライバシーポリシー」など,i降りつぶしの同期機能には直接関係のないリンクがたくさん潜んでいます。そしてこれらがタップされた場合,i降りつぶし内部ではなく,Safariを起動してそちらでリンク先を開く必要があります。i降りつぶしの画面はあくまでもWebビューであってフルスペックのWebブラウザではないため,その先のリンク遷移を十分に行えないからです。

一方,⁠連携アプリを認証」「キャンセル」がタップされた場合は,これをSafariに渡してはいけません。引き続きi降りつぶし内でハンドリングし,OAuthの手順に従ってリダイレクトを処理することで,最終的にはWebアプリへのログインが認められることになるからです。

結局,i降りつぶしは,⁠TwitterのOAuth認証ページ内のリンクのうち,どのリクエストがOAuth認証に直接必要なものなのか」を知っている必要があります。そしてそのURLへの遷移は認証の遷移としてアプリ内で管理し,それ以外へのリンクはSafariを起動して処理しなければなりません。

この実装は,どうしてもOAuthサービスプロバイダ(認証を行う側)の実装に依存してしまいます。

図12 同期実行中の画面

図12 同期実行中の画面

認証が成功すれば,後は同期機能を実行するのみです。それぞれの処理はメインスレッドから起動され,現在の実装では,iOSの機能であるGCD(Global Central Dispatch)を用いて,別スレッドによる並行処理をしています。

ここで問題になるのが,⁠SQLiteは1つの接続を複数スレッドから同時に使うことはできない」という大きな制限です。これは,厳密に言えば「不可能」なのではなく「1つの接続に関してマルチスレッド対策が一切取られていない」というべきものです。取られていないのですから,同時に複数スレッドから参照することが絶対にないようにすれば問題ないはずです。

意図して実装しない限り,フォアグラウンドにある画面でしかコードが実行されない,というiOSならではの制限を逆に生かし,i降りつぶしでは,ビューが表示されるときに並行処理キューを生成し,ビューが消える直前にキャンセルする,という処理を入れることで,SQLiteのマルチスレッド問題を回避しています(キャンセルには多少手間がかかっています⁠⁠。

そしてこのことは,同期画面から他の画面へと移動した場合,同期の実行を継続できない,ということも意味しています。実際,ナビゲーションバー右上のキャンセルボタンをタップすると,その時点で同期はキャンセルされますし,タブバーで別画面を選んだ場合やホームボタン押しでアプリがバックグラウンド化した際にも,アラートビューにより中断を通知しつつ,同期はキャンセルされます。

著者プロフィール

よねざわいずみ

合資会社ダブルエスエフ代表社員。学習塾講師やら芸能ライターやら劇団主宰やらいろいろ経て現在はよろず請負プログラマ。最近の開発はPHP,JavaScript,Java,MTプラグインなど。お仕事随時募集中。

Twitter:@yonezawaizumi

鉄道旅行ブログ:http://feelfine.blog.izumichan.com/