iOS 機器 (iPad や iPhone など) 向けのアプリケーションが次々に作成されていますが、それは何の不思議もありません。これらの機器は素晴らしい機能を備えている上に使いやすく、ユーザーが何百万人もいるため、これらの機器向けのアプリケーションを開発すれば大きな収益をもたらしてくれるからです。人々は iPad や iPhone などの鮮明なディスプレイに自分達の写真を表示させて楽しんでいるのです。
この記事では iOS 向けの写真のスライドショー・アプリケーションをゼロから作成します。そのために、サーバーへの XML コードと写真のアップロード、iOS アプリケーションの作成、画像ビューの追加、その XML の取得、そしてスライドショー・アニメーションの作成を行います。
スライドショーのサンプル・アプリケーションのバックエンドは、実際にはサーバーに配置される XML ファイルにすぎません。リスト 1 は、いくつかのサンプル画像を含む XML の例です。
リスト 1. photos.xml
<photos> <photo url="http://localhost/photos/CRW_0675.jpg" /> <photo url="http://localhost/photos/CRW_1488.jpg" /> <photo url="http://localhost/photos/CRW_3273.jpg" /> <photo url="http://localhost/photos/CRW_3296.jpg" /> <photo url="http://localhost/photos/CRW_3303.jpg" /> <photo url="http://localhost/photos/CRW_3359.jpg" /> <photo url="http://localhost/photos/CRW_3445.jpg" /> <photo url="http://localhost/photos/CRW_3752.jpg" /> <photo url="http://localhost/photos/CRW_3754.jpg" /> <photo url="http://localhost/photos/CRW_4525.jpg" /> <photo url="http://localhost/photos/CRW_4547.jpg" /> <photo url="http://localhost/photos/CRW_4700.jpg" /> <photo url="http://localhost/photos/CRW_4860.jpg" /> </photos> |
この XML は驚くほど単純です。<photos> タグは複数の <photo> タグを含んでいます。各 <photo> タグには表示対象となる画像の URL があります。これらの URL は完全修飾された絶対 URL でなければなりません。クライアント・アプリケーションは相対 URL を処理するブラウザーなどを使用せず、直接 URL をロードするからです。
バックエンドを完成させるために、写真への参照を含むように XML を変更し、その XML をサーバー上の既知の場所に配置します。すべてが想定どおりに進めば、Safari (または任意のブラウザー) を使用してその XML をブラウズすると、図 1 のような内容が表示されるはずです。
図 1. サーバー上に配置された XML
図 1 はリスト 1 の XML をテキスト・フォーマットで表示しています。これは単なる XML にすぎないため (そしてブラウザーには、参照すべき標準がないため)、表示される結果はブラウザーによって異なります。
URL が適切かどうかをテストするために、以下の手順を実行します。
- URL の 1 つを選択します。
- その URL をコピーしてブラウザーの URL 欄に貼り付けます。
- Return キーを押します。
すると図 2 のような画像が表示されるはずです。
図 2. サーバー上に配置された写真の 1 枚
サーバーに配置された写真は、XML の中に記述された URL の 1 つによって参照されます。XML が表示されない場合、あるいは写真が表示されない場合には、Web サーバーの構成と URL をチェックする必要があります。ブラウザーに写真が表示されない場合には、いま作成中の新しい iOS アプリケーションにも表示されないということです。
サーバーが構成され、写真がアップロードされると、iOS アプリケーションの作成を開始することができます。最初のステップとして Apple Developer Tools をインストールします (「参考文献」のリンクを参照)。以下に示すようにバージョンによって少し手順が異なります。
- Lion よりも前のバージョンの場合には、Apple Developer サイトから開発者ツールをダウンロードする必要があります (「参考文献」のリンクを参照)。
- Lion を実行している場合には、Mac App Store を使用して開発者ツールをダウンロードします (「参考文献」のリンクを参照)。
開発者ツールをインストールしたら、XCode 環境を実行します。XCode 環境は iOS と Mac OS X 両方の開発用に Apple が提供している IDE (統合開発環境) です。XCode 環境でメニューから「New Project (新規プロジェクト)」を選択します。すると、アプリケーション・ウィザードの最初のページが表示されるはずです (図 3 を参照)。このウィザードを使用して iOS または Mac OS X 用のアプリケーションを作成します。
図 3. アプリケーション・ウィザード
アプリケーションのテンプレートは何種類かあり、それらの中から選択することができます。このサンプル・アプリケーションの場合は「View-based Application (ビュー・ベースのアプリケーション)」を選択し、「Next (次へ)」をクリックします。するとウィザードの最終ページが表示されるはずです (図 4 を参照)。
図 4. プロジェクトのオプション
ウィザードの 2 番目のページでアプリケーションの名前を入力し、デフォルトで使用するデバイス・ファミリー (iPad または iPhone)
を選択します。このサンプル・アプリケーションの「Product Name (製品名)」は「slideshow」です。「Company Identifier (会社の ID)」フィールドの値は、このアプリケーションが com.jherrington という名前空間にあることを示しています。(もちろん、製品名や会社の ID
は自由に選択することができます。) 「Device Family (デバイスファミリ)」として iPad を選択し、「Next (次へ)」をクリックします。
これでプロジェクトが作成されました。この段階で最も適切な操作としては、インターフェースの左上にある大きな「Play (再生)」ボタンを選択し、このアプリケーションを実行します。このステップによってすべてがコンパイルされ、iPad エミュレーターが表示されます。
次のステップとして、画像を表示するための画像ビューを追加します。iOS フレームワークには多様な組み込みコントロールが用意されており、それらを使用してアプリケーションを作成することができます。このサンプル・アプリケーションでは UIImageView というコントロールを使用します。UIImageView を使用すると、アプリケーション内に集められた画像や、機器上にローカルに保存された画像、あるいはこのサンプル・アプリケーションのように Web サイトからダウンロードした画像を表示することができます。
UIImageView を追加するためには slideshowControllerView.XIB ファイルを開きます。このファイルは slideshowControllerView のユーザー・インターフェースを定義するファイルです。XIB を開いたら、オブジェクト・パレットから「Image View (画像ビュー)」を選択します (図 5 を参照)。
図 5. ビュー・コントローラーの XIB に UIImageView オブジェクトを追加する
「Image View (画像ビュー)」を選択したら、それをドラッグして slideshowControllerView にドロップします。通常は IDE が自動的にコントローラーを拡大縮小して画面に収まるようにします。そうならない場合には、表示領域全体に収まるように単純にコントロールをドラッグしてサイズを調整します。
コントロールにビューが表示されたら、アプリケーションのルック・アンド・フィールが最適になるようにパラメーターを設定します。図 6 は「Image View (画像ビュー)」コントロールの属性設定画面を示しています。
図 6. UIImageView を構成する
「Mode (モード)」と「Background (背景)」の 2 つを変更する必要があります。画像のサイズを変更しても元の画像とアスペクト比が変わらないように、「Mode (モード)」を「Aspect Fit (アスペクト比を保持)」に設定します。「Aspect Fit (アスペクト比を保持)」に設定しないと、画像は「Image View (画像ビュー)」の表示領域に合うように縦横がそれぞれに拡大縮小され、非常におかしな画像になってしまいます。
また、画像が必ずしも表示領域に収まらない場合があるため、「Background (背景)」属性を「Dark Text Color (暗い文字色)」に設定するか、あるいはカラー・ピッカーを使用して濃い黒を選択する必要があります。デフォルトで「Background (背景)」の値は「White (白)」になっていますが、ほとんどの写真は明るい白の背景では見にくいものです。
XIB ファイルを保存し、今度は SlideshowViewController.h ファイルに移ります。リスト 2 に示す簡単な変更を加えます。
リスト 2. SlideshowViewController.h
#import <UIKit/UIKit.h>
@interface slideshowViewController : UIViewController {
IBOutlet UIImageView *imgView;
}
@end |
slideshowViewController に Outlet を追加する必要があります。Outlet を追加することで、XIB で定義されたコントロールを slideshowViewController クラスに関連付けられるようになります。
Outlet を追加したら XIB ファイルに戻り、UIImageView を選択します。そしてコネクション・インスペクターを使用して
slideshowViewController クラス内で UIImageView オブジェクトを imgView 変数に関連付けます。
関連付けをしたら、slideshowViewController クラス自体のコードを変更して画像をロードします。リスト 3 は、このクラスの最初のバージョンが完成した状態を示しています。
リスト 3. SlideshowViewController.m
#import "slideshowViewController.h"
@implementation slideshowViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *imageURL = [NSURL URLWithString:@"http://localhost/photos/CRW_0675.jpg"];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
[imgView setImage:image];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end |
slideshowViewController クラスにおける重要な処理は viewDidLoad メソッドの中で行われています。このメソッドが現在行っている処理は、以下のとおりです。
- 指定された URL からデータをロードする処理
- そのデータを画像へ変換する処理
- imgView の
setImageメソッドを使用してその画像を表示する処理
この時点でアプリケーションを実行し、画像が表示されるかどうかをテストする必要があります。アプリケーションを実行すると、図 7 のような画面が表示されるはずです。図 7 は iPad エミュレーターに表示された画像を示しています。
図 7. サーバーから取得した最初の画像
画像が表示されない場合には、おそらく imgView の setImage メソッドを呼び出している部分に問題があります。UIImageView オブジェクトが imgView 変数に適切に接続されているかどうかを確認してください。それよりも前にアプリケーションが失敗している場合には、URL が適切ではないか、またはサーバーに何らかの問題があります。
これで iPad に画像を表示する方法を理解できたので、次のステップとして XML をロードし、表示するすべての画像のリストを取得します。iOS フレームワークには XML パーサーが組み込まれているため、単純にパーサー・オブジェクトを作成し、さまざまなタグに対するコールバックをリッスンします。
NSXMLParserDelegate インターフェースを使って UIViewController
クラスそのものを継承します。このインターフェースは iOS フレームワークに対し、このクラスが XML パーサーからコールバックを受信できることを伝えます。また、XML
から抽出した URL のリストを保持する photos という配列を追加する必要があります。リスト 4 は更新されたクラスを示しています。
リスト 4. photos を追加した SlideshowViewController.h
#import <UIKit/UIKit.h>
@interface slideshowViewController : UIViewController<NSXMLParserDelegate> {
IBOutlet UIImageView *imgView;
NSMutableArray *photos;
}
@end |
皆さんが iOS アプリケーションを数多く作成するようになるにつれ、委譲をさらに多く使用してさまざまな API へ接続するようになることに気付くはずです。例えばテーブルのデータのコールバック、UI 要素、GPS コールバック、等々に使用します。さらには皆さん自身のライブラリーのための独自のカスタム・インターフェースを作成することもできます。
XML パーサーを使用するためにはビュー・コントローラー・クラスを継承します (リスト 5 を参照)。
リスト 5. photos を追加した SlideshowViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
photos = [[NSMutableArray alloc] init];
NSXMLParser *photoParser = [[[NSXMLParser alloc]
initWithContentsOfURL:
[NSURL URLWithString:@"http://localhost/photos/index.xml"]] autorelease];
[photoParser setDelegate:self];
[photoParser parse];
NSURL *imageURL = [NSURL URLWithString:[photos objectAtIndex:0]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *image = [UIImage imageWithData:imageData];
[imgView setImage:image];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
if ( [elementName isEqualToString:@"photo"]) {
[photos addObject:[attributeDict objectForKey:@"url"]];
}
} |
これで、ビュー・コントローラー・クラスは viewDidLoad メソッドの中にパーサーを作成し、そのパーサーにサーバーから XML を取得させて構文解析させるようになりました。またビュー・コントローラー・クラスは、パーサーの委譲先が自分自身になるように設定し、コールバックを取得しています。
このサンプル・アプリケーションでは、タグを検出すると必ずトリガーされる didStartElement コールバックをリッスンする必要があります。次に didStartElement 関数はタグの名前が「photo」であるかどうかを調べます。photo タグの場合には、didStartElement は url 属性の値を photos 配列に追加します。
photos 配列が完成すると、viewDidLoad メソッドは動作を継続し、配列の最初の画像が表示されるように設定します。
アプリケーションを実行してどの程度まで進んだのかをテストします。XML
で指定された最初の画像がエミュレーターに表示されるはずです。最初の画像が表示されない場合には、サーバー上にある XML に問題があるかもしれません。didStartElement メソッドにブレークポイントを設定し、このメソッドが呼び出されるかどうかを確認します。呼び出されない場合には、サーバーから有効な XML が返されていないことになります。
最後のステップとして、写真の配列を使用してスライドショーをアニメーション化します。そのためには以下の 2 つが必要です。
- タイマー
- スライドショーの現在の場所を保持する変数
この両方をクラスの定義に追加します (リスト 6 を参照)。
リスト 6. 完成した SlideshowViewController.h
#import <UIKit/UIKit.h>
@interface slideshowViewController : UIViewController<NSXMLParserDelegate> {
IBOutlet UIImageView *imgView;
NSMutableArray *photos;
NSTimer *timer;
int currentImage;
}
@end |
timer は指定された間隔でイベントを起動するオブジェクトです。currentImage は単なる photos 配列のインデックスであり、このインデックスを使用して配列のすべての画像に対して繰り返し処理を行います。
リスト 7 はスライドショー・アプリケーションのコードの最終版です。
リスト 7. 完成した SlideshowViewController.m
#import "slideshowViewController.h"
@implementation slideshowViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
photos = [[NSMutableArray alloc] init];
NSXMLParser *photoParser = [[[NSXMLParser alloc]
initWithContentsOfURL:[NSURL URLWithString:
@"http://localhost/photos/index.xml"]] autorelease];
[photoParser setDelegate:self];
[photoParser parse];
currentImage = 0;
NSURL *imageURL = [NSURL URLWithString:[photos objectAtIndex:0]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
[imgView setImage:[UIImage imageWithData:imageData]];
timer = [NSTimer scheduledTimerWithTimeInterval: 5.0
target: self
selector: @selector(handleTimer:)
userInfo: nil
repeats: YES];
}
- (void) handleTimer: (NSTimer *) timer {
currentImage++;
if ( currentImage >= photos.count )
currentImage = 0;
NSURL *imageURL = [NSURL URLWithString:[photos objectAtIndex:currentImage]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
[imgView setImage:[UIImage imageWithData:imageData]];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict {
if ( [elementName isEqualToString:@"photo"]) {
[photos addObject:[attributeDict objectForKey:@"url"]];
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
@end |
リスト 7 には新しい要素が 2 つあり、1 つは viewDidLoad
メソッドの中でタイマーを作成していること、もう 1 つはタイマーが起動すると呼び出される handleTimer メソッドを追加していることです。handleTimer メソッドは単純に currentImage
をインクリメントし、配列の最後に達するとインデックスを最初に戻します。また handleTimer メソッドは、標準的な画像取得ロジックを使用して指定のインデックスの画像を取得し、その画像を表示します。
タイマーには 1 度だけ起動するモードと、連続的に起動するモードの 2 つのモードがあります。この例では viewDidLoad メソッドの中で YES を指定して繰り返しを行っています。そのため、アプリケーションが実行されている間、handleTimer メソッドは何度も呼び出されます。
この記事では基本的な iOS アプリケーションを作成しました。このアプリケーションを基に、いくつかの異なる方向に進むことができます。iOS CoreGraphics フレームワークには遷移機能が豊富にあり、それらを利用して画像間の変化をアニメーション化することができます。バックエンドで PHP を使用すると XML を動的に生成することができます。あるいはさらに、CoreAudio API を使用してスライドショー全体の背景に音楽を追加することもできます。
学ぶために
- Apple Developer
ポータル: IDE を入手したり、テスト機器のプロビジョニングをしたり、完成したアプリケーションを Apple Store にアップロードしたりすることができます。
- iOS Developer Library: Getting Started ドキュメントを読み、iOS 開発の基本について学んでください。このドキュメントには iOS アプリケーション開発に必須の情報が詳細に解説されています。
- W3C:
さまざまな標準について十分に調べてください。この記事に特に関係するのは XML に関する標準です。
- Objective-C
言語: Apple は Objective-C 独特の構文に関するスキルを磨くためのドキュメントを提供しています。
- 「土台から構築する iPhone
のチャット・アプリケーション」(Jack D. Herrington 著、developerWorks、2011年1月): サーバーからフロントエンドのユーザー・インターフェースに至るまで、iPhone のチャット・アプリケーションを構築する全過程を学んでください。
- 著者の
Jack Herrington が developerWorks に寄稿した他の記事 (2005年3月から現在まで): Ajax、JSON、PHP、XML、その他の技術に関する記事を読んでください。
- New to XML には、XML を学ぶために必要なリソースが豊富に用意されています。
- developerWorks の XML ゾーン:
DTD、スキーマ、XSLT など、XML の領域でのスキルを磨くためのリソースが豊富に用意されています。XML の技術文書一覧には、広範な話題を網羅した技術記事やヒント、チュートリアル、技術標準、IBM Redbooks が豊富に用意されています。
- IBM XML certification: XML および関連技術において IBM 認定技術者になる方法を参照してください。
- developerWorks の Technical events and webcasts: これらのセッションで最新情報を入手してください。
- developerWorks on Twitter: 今すぐ Twitter に参加して developerWorks のツイートをフォローしてください。
- developerWorks
podcasts: ソフトウェア開発者のための興味深いインタビューや議論を聞いてください。
- developerWorks on-demand demos: 初心者のための製品インストール方法やセットアップのデモから、上級開発者のための高度な機能に至るまで、多様な話題が解説されています。
製品や技術を入手するために
- Mac App Store: 皆さんの Mac にアプリケーションをダウンロードしてインストールしてください。
- IBM 製品の評価版: IBM
製品の評価版をダウンロードするか、あるいは IBM SOA
Sandbox のオンライン試用版で、DB2、Lotus、Rational、Tivoli、および WebSphere が提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。
議論するために
- developerWorks
のプロフィール: 今すぐプロフィールを作ってウォッチ・リストをセットアップしてください。
- XML
ゾーンのディスカッション・フォーラム: これらのフォーラムでは XML に関連する議論が行われています。
- developerWorks コミュニティー: 開発者向けのブログ、フォーラム、グループ、ウィキなどを利用しながら、他の developerWorks ユーザーとやり取りしてください。
