RSSの解析処理を実装したiPadアプリの作成方法をご案内します。
iPadアプリ作成時の基礎知識
RSS
スプリットビュー
スプリットビューは、左右に分割された画面のUI部品です。主に、左側に項目の一覧を、右側に各項目の詳細な内容を表示するために使います。左側ペイン(pane、枠)の幅はデフォルト値(既定値)では320ピクセルです。
ポップオーバー
ポップオーバーはポップアップウィンドウのようなUI部品です。任意のサイズで任意の場所に表示できます。
iPadでの画面切り替え
iPhoneではナビゲーションコントローラやタブバーコントローラを駆使して、次々と画面を切り替えながら様々な情報を表示しますが、iPadではスプリットビューとポップオーバーを使うことで画面の切り替え頻度を減らせるでしょう。
iPadが横向きのときはスプリットビュー、縦向きのときはポップオーバーで表示
ところで、「項目の一覧」の表示をiPadが横向きのときはスプリットビューの左側ペインで、iPadが縦向きのときはポップオーバーで表示する実装が多いようです。必ずしもこうしなければならないわけではありませんが、後ほど説明するXcodeのスプリットビューのテンプレートでプロジェクトを作成すると、自動的にこのような構成になります。おそらく、アップルが推奨する構成なのでしょう。
アプリの作成を開始!
iPadの特徴をざっくりと理解したところで、“iPadならでは”のアプリケーションを作ってみましょう。
RSSリーダー「nkRssReader」の作成手順
「ジェスチャー検出」機能とiPad用の「モーダルビュー」も実装
今回は、前述したiPad専用のUI部品であるスプリットビューとポップオーバーを用いたRSSリーダー「nkRssReader」を作ります。その中でiPhone OS 3.2で加わった「ジェスチャー検出」の機能とiPad用の「モーダルビュー」も実装しましょう。
nkRssReader
nkRssReaderの完成画面を以下に示す手順で作成していきます。
(1)Split Viewのテンプレートでプロジェクトを作成
「Split View-based Application」テンプレートを使う
初めの一歩はプロジェクトの作成です。Xcodeは様々なプロジェクトのテンプレートを用意していますが、その中に「Split View-based Application」があります。実は、このテンプレートを使えばスプリットビューとポップオーバーを持つアプリを簡単に作成できます。
新規プロジェクトを作成
Split View-based Applicationテンプレートを選択し、「nkRssReader」というプロジェクト名で新規プロジェクトを作成しましょう。
ビルド
プロジェクトができたら、早速ビルドしてみます。テンプレートからプロジェクトを作ると、複数のファイルが生成され、初期状態でビルド可能になっています。ビルドするとどのような画面になるでしょうか。
iPadのシミュレータ実行
ビルドしてiPadのシミュレータで実行させた画面では、画面左上の「Root List」ボタンを押すとポップオーバーのウィンドウが現れます。先ほども述べましたが、既にこの時点でiPadの状態、すなわち縦向きか横向きかに応じたポップオーバーとスプリットビューの自動切り替えが実装されています。なお、iPadシミュレータはメニューの「ハードウェア」→「反時計回りに回転」または「時計回りに回転」で回転できます。
RootViewControllerクラス
スプリットビューの左側ペインまたはポップオーバーには「Root View Controller」と書かれています。ここから容易に推測できますが、これらのUI部品はRootViewControllerクラスで扱います。また、「Detail view content goes here」と書かれているメイン画面を扱うのはDetailViewControllerクラスです。これらの点を把握した上でプログラミングを進めましょう。なお、今回のアプリではnkRssReaderAppDelegateクラスに変更点はありません。テンプレートが生成したものをそのまま使います。
Root Listボタンの処理
さて、Root ListボタンはiPadが縦向きだとが現れ、横向きだと消えます。手始めに、この処理を制御している部分から見ていきましょう。それがDetailViewController.mの中にある2つのメソッドです。いずれもUISplitViewControllerDelegateプロトコルで宣言されます。
iPadが縦向き、あるいは横向きになったとき
メソッド名が非常に長いのですが、splitViewController:willHideViewController:withBarButtonItem:forPopoverController:はiPadが縦向きになったときに、splitViewController:willShowViewController:invalidatingBarButtonItem:はiPadが横向きになったときにOSが呼び出します。ですから、これらの中に縦向き、あるいは横向きになったときの処理が記述されています。
ボタンをもう1つ付け加える
試しに少し改造してみましょう。ボタンをもう1つ付け加えてみます。
ボタンが押されたときのメソッドを宣言
DetailViewController.hでボタンのUI部品であるUIBarButtonItemクラスのインスタンス変数と、ボタンが押されたときのメソッドを宣言します。次に、書き換えます。これで「2つ目のボタン」というボタンを追加できました。ボタンを押すとテキストが「2つ目のボタンが押されました」に書き変わります。UI部品はこのようにして追加できます。
(2)記事タイトル一覧の表示を実装する
左側ペインまたはポップオーバー時
nkRssReaderは、スプリットビューの左側ペインまたはポップオーバーにRSSの記事タイトル一覧を、メイン画面にRSSの本文を表示します。これらの機能を実装しましょう。
テンプレートが生成したソースコードを確認する
まず、記事タイトル一覧の実装です。既に「Row 0」「Row 1」…と表示されているので、これを手がかりにテンプレートが生成したソースコードを見ていきます。
文字列「Row」でプロジェクト全体を検索
文字列「Row」でプロジェクト全体を検索すると、Rowを表示しているのは、RootViewController.mのtableView:cellForRowAtIndexPath:メソッドであることが判明します。同メソッドは、「テーブルビュー」の各セル(項目)の表示内容を設定するメソッドで、iPhoneプログラミングではおなじみです。ポップオーバーの中身のようなUI部品がテーブルビュー(UITableViewクラス)です。
RootViewController.m内で、テーブルビューの表示内容を制御
これで実装の方針が固まりました。RootViewController.m内で、テーブルビューの表示内容を制御しましょう。また、RSSの読み込み処理も実装します。
テーブルビューに関連する主な修正部分を抜き出す
RootViewController.mのテーブルビューに関連する主な修正部分を抜き出し、ユーザーがテーブルビューのセルを選択するとtableView:didSelectRowAtIndexPath:メソッドが呼ばれます。同メソッドでは選択された記事の各種データ(タイトル、タイムスタンプ、リンク)を取り出し、DetailViewController.hで宣言している変数(articleTitle、pubDate、link)に格納しています。後ほど、これらの変数を用いて、メイン画面に本文を表示します。
(3)メイン画面に記事本文を表示する
Interface Builderを起動
メイン画面に記事の本文を表示する処理を実装しましょう。まずは、プロジェクトのDetailView.xibをクリックしてInterface Builderを起動します。Viewというウィンドウが出るので、ここにUI部品を並べながら画面を設計していきます。今回は、本文をUITextView、タイトルと日付をUILabelで表示することにします。また、画面上部のツールバー(UIToolbar)に「Webサイトを表示」ボタンと、ボタンを右端に表示するためのスペース(Flexible Space)を配置します。UI部品は階層構造になります。
各種の変数を宣言
Interface Builderでの画面設計が終わったら、UI部品に対応するために、DetailViewController.hで各種の変数を宣言します。“回転”ジェスチャー検出用のUIRotationGestureRecognizerクラスと、“つまむ”ジェスチャー検出用のUIPinchGestureRecognizerクラスのインスタンス変数も宣言しておきましょう。
Interface Builderで「Autosizing」を設定
これでメイン画面の実装はほぼ完了なのですが、このままビルトすると1つ気になることが起こります。iPadが縦向きの場合を想定してUI部品を配置してきたので、iPadを横向きにすると本文と日付の右端が画面からはみ出てしまいます。これを修正するために、Interface Builderで「Autosizing」を設定しましょう。Autosizingの赤い矢印や├─┤マークをオン/オフすることで、状態に応じたUI部品の場所とサイズの自動調整を設定できます。どのように自動調整されるかは右側の画面でリアルタイムにアニメーション表示されるのですぐに把握できます。ここでは、記事の本文は常に中央に配置されるように、日付は画面の右側に張り付くようにします。
基本的なRSSリーダーが完成
ここまでで基本的なRSSリーダーが完成しました。
(4)ジェスチャー検出の実装
ジェスチャーによる背景の明るさの変更とテキストの拡大縮小機能を実装
iPhone OS 3.2以降には「UIGestureRecognizerクラス」があるので、各種ジェスチャーを容易に検出できるようになりました。現時点でUIGestureRecognizerクラスから派生する表1のクラスがあり、長押し、ピンチ(つまむ)、スワイプ(なぞる)などを認識可能です。nkRssReaderでは2本指の回転を検出するUIRotationGestureRecognizerと、ピンチイン・ピンチアウトを検出するUIPinchGestureRecognizerを使い、ジェスチャーによる背景の明るさの変更とテキストの拡大縮小機能を実装してみます。
プログラムで実装する必要がある処理
ジェスチャーを扱うプログラムで実装する必要がある処理は次の通りです。
(A)「リコグナイザ」と呼ばれるインスタンスの生成と目的のジェスチャーが認識されたときに実行するメソッドの指定
(B)ジェスチャーを検出したいビューにリコグナイザを登録
(C)デリゲートの指定
2本指の回転、ピンチイン・ピンチアウトを検出したときの処理を指定
これらの処理はビューが表示されたときに呼ばれるviewDidLoadメソッドに記述しました。2本指の回転を検出したときはhandleRotationGesture:メソッドを、ピンチイン・ピンチアウトを検出したときはhandlePinchGesture:メソッドを呼ぶように@selectorで指定しています。また、デリゲートには「self」(ここではDetailViewControllerのオブジェクト)を設定しました。このような実装は従来のiPhoneプログラミングでも多用されていましたね。
リコグナイザから角度または拡大率の値を取得
handleRotationGesture:とhandlePinchGesture:メソッドは、各リコグナイザ(recognizer)からrotaion(角度)またはscale(拡大率)の値を取得し、それらの値に応じて背景の明るさやフォントサイズを変化させます。
ジェスチャーの検出状態を表す「recognizer.state」
また、親クラスであるUIGestureRecognizerクラスにはstateプロパティがあり、ジェスチャーの検出状態を表します。つまり、stateを監視することでジェスチャーの状態がわかります。ここでは「if(recognizer.state == UIGestureRecognizerStateEnded)」と記述し、ジェスチャーが終了したか否かを判定しています。
ジェスチャーは複数の種類を同時に検出可能
ところで、ジェスチャーは複数の種類を同時に検出可能です。メソッドで「YES」を返せば同時検出に対応できます。
(5)Webサイトをモーダルビューで表示
記事のWebサイトを表示する機能
もう一歩で完成です。記事のWebサイトを表示する機能を付けます。
Webページの表示にはUIWebViewを使用
まず、Xcodeで新たなクラス「WebViewController」とInterface Builderで編集するためのxibファイルを作ります。「新規ファイル」ダイアログで「UIViewController subclass」のテンプレートを選び、ファイルを作成します。ファイル名は「WebViewController.m」としました。これでWebViewController.m、WebViewController.h、WebViewController.xibの3ファイルが生成されます。その後、WebViewController.xibをInterface Builderで開いて、UI部品を配置してください。Webページの表示にはUIWebViewを使います。
WebViewControllerクラス
WebViewControllerクラスでは、viewDidLoadメソッドでUIWebViewにURLを設定してWebページを表示しています。
Webサイトの表示はモーダルビュー
さて、Webサイトの表示はモーダルビューにします。iPadではモーダルビューの表示方法が追加されたので、それを使いましょう。
iPadでのモーダルビュー
iPhoneのモーダルビューは、そのときのビューの上に画面全体を覆う新しいビューを表示するものでした。一方、画面の大きいiPadでは、ビューの一部をグレイアウトした状態で表示させつつ、別のビューをモーダルビューで表示可能です。
「Webサイトを表示」ボタンを押すと、記事のWebサイトをモーダルビューで表示
nkRssReaderでは、「Webサイトを表示」ボタンを押すと、記事のWebサイトをモーダルビューで表示します。この機能をDetailViewControllerクラスに追加しましょう。「Webサイトを表示」ボタンを押すと、tapWebButtonメソッドが呼ばれるようにします。同メソッドの中にモーダルビューの設定を記述します。
様々なモーダルビューの表示方法を指定
「modalPresentationStyle」は、WebViewControllerの親クラスであるUIViewControllerのプロパティです。これに様々なモーダルビューの表示方法を指定できます。
モーダルビューの表示アニメーションのスタイルを指定可能
また、「modalTransitionStyle」というプロパティもあります。このプロパティには、ビューの表示アニメーションのスタイルを指定可能です。いろいろな値を設定して、モーダルビューの表示や動作の変化を試してみましょう。
全画面切り替えには
なお、modalTransitionStyleにUIModalTransitionStylePartialCurlを指定する場合は、全画面切り替えにする必要があるので、modalPresentaionStyleでUIModalPresentationFullScreenを指定します。
アプリ完成
これでついに完成です!いろいろと試してみたり、改造してみてください。このアプリではRSSフィードをhttp://images.apple.com/jp/main/rss/hotnews/hotnews.rssに決め打ちしていますが、これを変更したり、ブックマーク機能を付けたり、ユーザーが入力できるように機能強化するのもよいでしょう。
iPadの特長
メモリーは少ない
画面サイズとプロセッサの性能はノートPCのそれに近づきつつあるiPadですが、メモリー容量はiPhone 3GSと同じ256Mバイトのままで、まだまだ少ないです。プログラミング時に最も注意すべき点は、従来のiPhoneと同様、メモリーの使用量や解放し忘れです。リファレンスカウンタ方式によるメモリー管理手法もiPhoneと同じです。なお、iPhone 4は512Mバイトのメモリーを搭載しています。
ジェスチャーの検出が簡単に!
ジェスチャーはiPhone/iPadが持つ最大の特徴の1つです。指で引き伸ばしたり、つまんだりといった動作でアプリケーションを操作できます。
これまでは、プログラム側でタッチ情報を解析判定
以前は、ボタンやスクロールビューなど特定のUI部品以外では、プログラマがタッチ情報を解析して、どのようなジェスチャーが行われたかを判定する必要がありました。
iPhone OS 3.2以降では、ジェスチャーの検出が容易に
iPhone OS 3.2以降では、このジェスチャーの検出が簡単になりました。スワイプやピンチイン、ピンチアウト、長押しなど、頻繁に使われるジェスチャーに対しては専用の認識クラスが導入されています。それらを使えば容易にジェスチャーを検出可能です。
iPhone OS(iOS)の2つの方向性
最後に、iPhone OS(iOS)がこれまでいかに発展してきたか、大まかな傾向を紹介します。大きく2つの方向性があります。1つは新しいハードウエアに対応するクラスや関数が順次追加される流れ、もう1つはMac OS Xには搭載されているもののiPhone OSでは削られていた機能が新規追加される(復活する?)流れです。
iOSの進化とアプリ
こうした傾向はしばらく続くでしょう。OSのバージョンアップは、時には動いていたアプリが突然動かなくなるような困った事態を生み出しますが、新しい機能が増えればアプリで実現できることも増えるはずです。アプリ作成を楽しみながら、iOSの進化を追っていきましょう。
*1 2010年8月上旬時点で、iPadのOSは「iPhone OS 3.2」(バージョン3.2)です。一方、iPhoneの最新OSは「iOS 4」(バージョン4)です。iPad用のiOS 4は今秋にリリースされる見込みです。
*2 iPhoneとの違いということでは、iPadはカメラを内蔵していません。また、iPadのWi-FiモデルにはGPSがありません。ほかにも「写真」アプリの操作法など、細かな違いがあります。
*3 iPhone 4もA4プロセッサを搭載しています。
*4 iPhone 3GSが搭載するプロセッサのクロック周波数は600MHzと推測されています。
NSXMLParserクラスでRSSの解析処理を実装する
RSSの解析処理
NSXMLParserクラス
RSSの解析処理には「NSXMLParserクラス」を使いました。NSXMLParserは、parseメソッドの実行でXMLファイルの解析を開始します。
RootViewController.mのparseXMLFileAtURL:メソッド
プログラムでは、RootViewController.mのparseXMLFileAtURL:メソッドの中で、NSXMLParserオブジェクトを初期化し、parseメソッドを実行しています。以下のようなコードです。
// NSXMLParser *rssParserをRootViewController.hで宣言
// 初期化
rssParser = [[NSXMLParser alloc] initWithContentsOfURL:url]; // urlにはRSSフィードが入っている
[rssParser setDelegate:self]; // デリゲートの設定
[rssParser parse]; // 解析処理を開始
「NSXMLParserDelegateプロトコル」の各種メソッド
解析処理を始めると、NSXMLParserオブジェクト(rssParser)は「NSXMLParserDelegateプロトコル」の各種メソッドを状況に応じて呼び出すので、それらを実装します。具体的にはメソッド群です。プログラムでは5個のメソッドをRootViewController.mに実装しました。例えば、parser:foundCharacters:は次のように記述しています。
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if ([tmpElement isEqualToString:@"title"]) {
[tmpTitle appendString:string];
} else if([tmpElement isEqualToString:@"link"]) {
[tmpLink appendString:string];
} else if ([tmpElement isEqualToString:@"description"]) {
[tmpDescription appendString:string];
} else if ([tmpElement isEqualToString:@"pubDate"]) {
[tmpDate appendString:string];
}
}
要素の種類を判別して、文字列を取得
要素の種類を判別して、文字列を取得します。なお、parseXMLFileAtURL:メソッドはviewDidLoadメソッドの中で次のように呼び出しています。
// RSSフィードの設定
rsspath = @"http://images.apple.com/jp/main/rss/hotnews/hotnews.rss";
[self parseXMLFileAtURL:rsspath];
rsspathのRSSフィード
rsspathのRSSフィードを変更して、いろいろ試してみてください。
portraitとlandscape
英語では縦向きを「portrait orientation」、横向きを「landscape orientation」と言います。アップルの技術文書でも使われているので覚えておきましょう。