カメラアプリの作り方の2回めだ。今回は、カメラ機能を使って写真を撮ってみよう。

UIImagePickerControllerクラス

写真を撮るために使うのは、イメージピッカーと呼ばれる機能だ。この機能は、UIImagePickerControllerというクラスから使える。このクラスの継承関係を確認しておこう。UINavigationControllerが親クラスになっている事を覚えておいてほしい。

イメージピッカーは、カメラを使う事ができる機能なのだが、それ以外にもフォトアルバムにアクセスする事もできる。フォトアルバムは、iPhotoと同期する事のできる写真のライブラリだ。これを使う事で、Macにある画像をiPhoneアプリで使ったり、また逆にiPhoneアプリで撮影した写真をMacに送る事ができる。

どちらの機能を使うかを指定するには、UIImagePickerControllerクラスの、sourceTypeというプロパティを使う。これはUIImagePickerControllerSourceTypeという型になり、対応する3つの定数が定義されている。

UIImagePickerController.h

@property(nonatomic) UIImagePickerControllerSourceType sourceType;

enum {
    UIImagePickerControllerSourceTypePhotoLibrary,
    UIImagePickerControllerSourceTypeCamera,
    UIImagePickerControllerSourceTypeSavedPhotosAlbum
};

UIImagePickerControllerSourceTypePhotoLibraryは、フォトライプラリを表す。UIImagePickerControllerSourceTypeCameraは、カメラだ。3つめのUIImagePickerControllerSourceTypeSavedPhotosAlbumは、iPhoneとiPod touchで少し挙動が異なり、iPhoneの場合はそのカメラで撮影したカメラロールが、iPod touchの場合は「Saved Photos」というフォルダを開く事になる。

イメージピッカーには他に、allowsImageEditingというプロパティもある。これは、撮影または選択した画像を編集できるようにする設定だ。編集可能にすると、移動と拡大/縮小を行って、画像のクロップを行えるようになる。

UIImagePickerController.h

@property(nonatomic) BOOL allowsImageEditing;

イメージピッカーの表示

では、実際にUIImagePickerControllerクラスを使ってみよう。前回のソースコードを拡張する形で説明していく。前回は、ツールバーのボタンを押してアクションシートを表示し、そのデリゲートが呼び出されるところまで説明した。このデリゲートの中から、イメージピッカーの表示を行ってみる。

CameraViewController.m

- (void)actionSheet:(UIActionSheet*)actionSheet
        clickedButtonAtIndex:(NSInteger)buttonIndex
{
    // ボタンインデックスをチェックする
    if (buttonIndex >= 3) {
        return;
    }

    // ソースタイプを決定する
    UIImagePickerControllerSourceType   sourceType = 0;
    switch (buttonIndex) {
    case 0: {
        sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        break;
    }
    case 1: {
        sourceType = UIImagePickerControllerSourceTypeCamera;
        break;
    }
    case 2: {
        sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
        break;
    }
    }

    // 使用可能かどうかチェックする
    if (![UIImagePickerController isSourceTypeAvailable:sourceType]) {
        return;
    }

    // イメージピッカーを作る
    UIImagePickerController*    imagePicker;
    imagePicker = [[UIImagePickerController alloc] init];
    [imagePicker autorelease];
    imagePicker.sourceType = sourceType;
    imagePicker.allowsImageEditing = YES;
    imagePicker.delegate = self;

    // イメージピッカーを表示する
    [self presentModalViewController:imagePicker animated:YES];
}

まず、アクションシートで押されたボタンをチェックする。アクションシートを作るときにボタンのリストを渡したが、そのインデックスが得られる。ここでは、0から2ならばイメージピッカーを表示するためのボタン。3ならばキャンセルとなっている。そして、ボタンのインデックスに応じて、ソースタイプを決定する。

ソースタイプが決まったら、そのタイプが現在の動作環境で使用可能かどうかのチェックを行う。これには、UIImagePickerControllerのクラスメソッドである、isSourceTypeAvailable:を使う。

UIImagePickerContrller.h

+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType;

たとえば、iPod touchでカメラ機能を使おうとすると、ここで使えないという事が分かる訳だ。この実装では単にreturnで抜けているだけだが、アラートダイアログなどを出してユーザに通知する事も必要だろう。

そして、イメージピッカーを作る。UIImagePickerControllerのインスタンス化を行う。そして、sourceType、allowsImageEditingといったプロパティを設定していく。さらに、このクラスをデリゲートとして設定しておく。そのとき、このクラスをUINavigationControllerDelegateおよびUIImagePickerControllerDelegateプロトコルに準拠させておこう。

最後に、イメージピッカーを表示させる。これには、UIViewControllerのpresentModalViewController:animated:というメソッドを使う。

UIViewController.h

- (void)presentModalViewController:(UIViewController*)modalViewController animated:(BOOL)animated;

このメソッドを使うと、指定したUIViewControllerが管理しているビューを、モーダルとして、つまり前画面に覆いかぶさる感じで表示する事ができる。UIImagePickerControllerは、冒頭で説明したようにUIViewControllerのサブクラスなので、このようにして使われる事を想定しているのだ。

逆に言うと、イメージピッカーを表示するクラスは、ビューコントローラとなっていないと使用が難しいという事だ。Cocoa Touchでは、このようにビューコントローラの使用を前提としているものが多い。可能な限り、ビューコントローラの使用を前提としたクラス設計を心がけよう。

実際の撮影動作

ここまでのソースコードを、実際に動作させてみよう。まず、フォトライブラリを表示してみる。

このデバイスのフォトライブリにある画像を選択する事ができる。この画面は、標準アプリの「写真」と同じものである事が分かると思う。

次に、カメラ機能を使ってみよう。ソースタイプにカメラを指定してイメージピッカーを表示させると、次のような撮影画面になる。

撮影するときの画像の動き方は、標準のカメラアプリと同じだ。右下のカメラボタン押す事で、撮影する事ができる。標準のカメラと違うのは、この後画像の編集を行う事ができるところだ。編集モードでは、画像の移動および拡大縮小が行える。

「Retake」ボタンを押せば、もう一度撮影になる。「Save Photo」ボタンを押せば、イメージピッカーのデリゲートにメッセージが飛ぶ事になる。

イメージピッカーを隠す

イメージピッカーを使って、写真の保存、画像の選択、またはキャンセルを選択すると、デリゲートにメッセージが飛ぶ。何らかの画像が取得できた場合は、imagePickerController:didFinishPickingImage:editingInfo:。キャンセルをした場合は、imagePickerControllerDidCancel:だ。

これらのメソッドの中では、まずイメージピッカーを隠す処理を行わなくてはいけない。イメージピッカーの表示にはpresentModalViewController:animated:というメソッドを使ったが、これを隠すときはdismissModalViewControllerAnimated:を使う。

UIViewController.h

- (void)dismissModalViewControllerAnimated:(BOOL)animated;

次のように、イメージピッカーのデリゲートメソッドを実装しておこう。

CameraViewController.m

- (void)imagePickerController:(UIImagePickerController*)picker
        didFinishPickingImage:(UIImage*)image
        editingInfo:(NSDictionary*)editingInfo
{
    // イメージピッカーを隠す
    [self dismissModalViewControllerAnimated:YES];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
{
    // イメージピッカーを隠す
    [self dismissModalViewControllerAnimated:YES];
}

これで、一通りカメラ機能が使えるようになった。次回は、撮影した画像を保存して表示する手順を説明しよう。

ここまでのソースコード: Camera-2.zip