外部イメージを利用可能なUIImagePickerControllerもどきのクラスを試してみた

iPhoneiPod touch内の写真をアプリから利用する場合、UIImagePickerControllerという便利なクラスがあるのだが、このクラスはiPhoneiPod touchのフォトアルバム内にある写真しか利用出来ず、自分のアプリにバンドルされた画像やウェブ上にある画像を扱う事は出来ない。
しかし、これらの画像を扱う事を可能にした、UIImagePickerControllerもどきのJPImagePickerControllerというクラス(MITライセンス)をJenna Paradiesさんという方が公開していたので、試しに使ってみた。


[準備]
以下からソースコードをダウンロードし、Classesフォルダ配下のファイルを全てiPhoneアプリのプロジェクトにコピーする。

あとはアプリケーションにバンドルする画像を用意すれば準備は終了である。今回はサムネイル画像(1s.jpg〜12s.jpg)とオリジナル画像(1.jpg〜12.jpg)をそれぞれ12個用意した。


[利用方法]
基本的な流としては、JPImagePickerControllerDelegateとJPImagePickerControllerDataSourceという二つのプロトコルを導入し、必要なメソッドを実装していく形になる。実装が必要なメソッドは以下の5つ。

// ユーザがキャンセルボタンを押した際の処理を書く
- (void)imagePickerDidCancel:(JPImagePickerController *)picker;
// ユーザが画像を選択した際の処理を書く
- (void)imagePicker:(JPImagePickerController *)picker didFinishPickingWithImageNumber:(NSInteger)imageNumber;
// ImagePicker上に表示する画像の数を返す
- (NSInteger)numberOfImagesInImagePicker:(JPImagePickerController *)picker;
// ImagePicker上に表示するサムネイル画像を返す
- (UIImage *)imagePicker:(JPImagePickerController *)picker thumbnailForImageNumber:(NSInteger)imageNumber;
// サムネイル画像を選択した後に表示されるオリジナル画像を返す
- (UIImage *)imagePicker:(JPImagePickerController *)picker imageForImageNumber:(NSInteger)imageNumber;


具体的な実装は以下のような形になる(ボタンを押したらこのJPImagePickerControllerを表示するという例)。

#import "JPImagePickerDetailController.h"
@interface JPImagePickerTestViewController : UIViewController
<JPImagePickerControllerDelegate, JPImagePickerControllerDataSource> {
    UIImageView *imageView;
}
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
- (IBAction)showJPImagePicker;
@implementation ImagePickerTestViewController
@synthesize imageView;
- (IBAction)showJPImagePicker {
    JPImagePickerController *picker = [[JPImagePickerController alloc] init];
    picker.imagePickerTitle = @"My Photo Albums";
    picker.delegate = self;
    picker.dataSource = self;
    [self presentModalViewController:picker animated:YES];
    [picker release];
}

- (NSInteger)numberOfImagesInImagePicker:(JPImagePickerController *)picker {
    return 12;
}

- (UIImage *)imagePicker:(JPImagePickerController *)picker thumbnailForImageNumber:(NSInteger)imageNumber {
    return [UIImage imageNamed:[NSString stringWithFormat:@"%ds.jpg", imageNumber + 1]];
}

- (UIImage *)imagePicker:(JPImagePickerController *)imagePicker imageForImageNumber:(NSInteger)imageNumber {
    return [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg", imageNumber + 1]];
}

- (void)imagePickerDidCancel:(JPImagePickerController *)picker {
    [picker dismissModalViewControllerAnimated:YES];
}

- (void)imagePicker:(JPImagePickerController *)picker didFinishPickingWithImageNumber:(NSInteger)imageNumber {
    imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg", imageNumber + 1]];
    [picker dismissModalViewControllerAnimated:YES];
}
@end

JPImagePickerControllerを表示すると以下のように、UIImagePickerControllerとそっくりの画面が表示される。違いはアプリにバンドルされた写真を表示しているという点である。

また、もう一つの違いは表示された画像をタッチした時の挙動。UIImagePickerControllerの場合、その時点でタッチした画像データをアプリで取得出来るのだが、JPImagePickerControllerではそのかわりに以下のような詳細画面が表示される。そしてこの詳細画面でユーザが「Choose」ボタンを押すと、画像データの番号が取得出来るという仕組みになっている。

[まとめ]
今回はローカルの画像データを利用したが、若干上記のコードを修正する事で、リモートの画像データを表示させる事も可能と思われる。また、本クラスはオリジナルのUIImagePickerControllerとは若干挙動が違うものの、比較的利用しやすいクラスなので色々応用出来そうな感じである。
詳細画面は画像の拡大等をサポートしていないので、より実用的にするにはこの辺りをもう少し自前で改善する必要がありそうな気がする。

[参考記事]