☆Cocoa Touch UIKit勉強(3)
画像取得・選択;UIImagePickerController
UIImagePickerControllerは、カメラでの撮影、および撮影後画像の選択(取得)を制御するためのビューである。 iPod touch(iPhone)のカメラアプリケーションとiPadを含む写真アプリケーションは主にこれから出来ている。
静止画(still image)及び動画(movie)が対象になる。 なぜかUINavigationControllerの子クラスになっている(デリゲートの関係か)。
カメラまわりはiOS4.0、というか第4世代iPhone/iPod touchで大幅に機能アップされたので、 それ以降しか対応していない項目も多い。 当然のことながら、カメラを持っていないiPad1では無効な部分も多い。

 iPadではUIPopoverControllerの中からしか呼び出せない。

 iOS4.3ではオーバーレイに関する仕様が変わった模様。iOS4.2.1までで正常に表示されていても、4.3では正常表示されない可能性があるので 確認が必要である。私が確認したのは以下の点。 また、前面カメラで撮影すると、撮影後の画像の左右が逆になる。 カメラアプリケーションだけでなく、UIImagePickerControllerレベルでそうなってる。 iOS4.3にしてから気がついたので、iOS4.2.1ではどうだったか不明。 仕様かもしれないが、バグに近いと思う。

UIImagePickerController
メソッド名動作
+(NSArray*)availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice カメラデバイスでサポートされるキャプチャーモードを返す
+(NSArray*)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType 画像取得源として利用可能なメディアタイプを返す
+(BOOL)isCameraDeviceAvailable:(UIImagePickerControllerCameraDevice)cameraDevice 指定のカメラが使えるかどうかを返す
+(BOOL)isFlashAvailableForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice 指定カメラにフラッシュ機能があるかどうかを返す
+(BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType デバイスが指定された画像取得源を用いた選択メディアをサポートするかどうかを返す
-(void)takePicture 指定されたカメラで静止画を撮影する
-(BOOL)startVideoCapture 指定されたカメラで動画撮影を開始する
-(void)stopVideoCapture 動画撮影を終了する

プロパティ名属性内容
id <UINavigationControllerDelegate,UIImagePickerControllerDelegate> delegateSデリゲートを設定する
UIImagePickerControllerCameraCaptureMode cameraCaptureModeRW 画像撮影モードを設定する
UIImagePickerControllerCameraCaptureMode(enum値)
UIImagePickerControllerCameraCaptureModePhoto静止画
UIImagePickerControllerCameraCaptureModeVideo動画
UIImagePickerControllerCameraDevice cameraDeviceRW 画像撮影デバイスを指定する
UIImagePickerControllerCameraDevice(enum値)
UIImagePickerControllerCameraDeviceRear背面カメラ(デフォルト)
UIImagePickerControllerCameraDeviceFront前カメラ
UIImagePickerControllerCameraFlashMode cameraFlashModeRW 撮影時のフラッシュ状態を指定する
UIImagePickerControllerCameraFlashMode(enum値)
UIImagePickerControllerCameraFlashModeOff 点灯しない
UIImagePickerControllerCameraFlashModeAuto 自動
UIImagePickerControllerCameraFlashModeOn 点灯する
UIView *cameraOverlayViewTデフォルトの画像ピッカーの上に表示するカスタムビューを指定する
ところが、オーバーレイにはいろいろ制約があるので、自前でUIViewを重ねた方が良いと思う。 回転処理とかは自分でやらないといけないけど。
NSArray *mediaTypesCメディアタイプの設定
利用可能なメディアタイプはavailableMediaTypesForSourceType:で得られる
メディアタイプ(UTI Image Content Types) ( CFStringRef 構造体値)
kUTTypeImage 画像データ(抽象識別子);デフォルト
kUTTypeJPEG JPEG
kUTTypeJPEG2000 JPEF2000
kUTTypeTIFF TIFF
kUTTypePICT QuickDraw PICT
kUTTypeGIF GIF
kUTTypePNG PNG
kUTTypeQuickTimeImage QuickTime('qtif')
kUTTypeAppleICNS Apple icon
kUTTypeBMP Windows bitmap
kUTTypeICO Windows icon
BOOL showsCameraControls YES=デフォルトのカメラコントロールがpicker内に見える
NO=cameraOverlayViewプロパティで指定するカスタムオーバーレイビューを表示する
UIImagePickerControllerSourceType sourceTypeRW 画像取得源
UIImagePickerControllerSourceType(enum値)
UIImagePickerControllerSourceTypePhotoLibrary 写真ライブラリ
UIImagePickerControllerSourceTypeCamera 内蔵カメラ
UIImagePickerControllerSourceTypeSavedPhotosAlbum 保存された写真
NSTimeInterval videoMaximumDuration 動画の最大撮影時間を設定する
内蔵メモリには限りがあるので、無限撮影はできないようになっている。 時間以内でも空き容量がなくなったらたぶん止まる。
UIImagePickerControllerQualityType videoQualityRW 画質
UIImagePickerControllerQualityType(enum値)
UIImagePickerControllerQualityTypeHigh カメラでサポートしている最高画質
UIImagePickerControllerQualityType640x480 640*480
UIImagePickerControllerQualityTypeMedium 中画質(デフォルト)
WiFiで転送するにちょうど良いサイズ
UIImagePickerControllerQualityTypeLow 低画質

デリゲートは2つのプロトコルを指定する。
UINavigationControllerDelegateについては ナビゲーションコントローラー;UINavigationControllerの項参照のこと。
UIImagePickerControllerDelegate
メソッド名動作
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 静止画を撮影、または静止画または動画を選択したとき呼び出される。
infoには以下の値が入る。
  • 静止画選択時:オリジナル画像と編集された画像を含んでいる辞書
  • 動画選択時 :ファイルシステムURL
編集されているときには編集情報も含む。
info辞書のキー値(NSString const*値)意味辞書内容
UIImagePickerControllerMediaTypeユーザーが選択したメディアタイプkUTTypeImage/kUTTypeMovie
UIImagePickerControllerOriginalImage撮影画像UIImage
UIImagePickerControllerEditedImage編集された画像UIImage
UIImagePickerControllerCropRectオリジナル画像内編集領域長方形CGRectの不透明なタイプを含んでいるNSValueオブジェクト
UIImagePickerControllerMediaURLファイルシステムURLNSURL
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker 選択処理が中断されたとき呼び出される。
こんな風にして撮影した画像を取り出す。 この例では、撮影が終わったら、即カメラ画面を消すようにしている。
-(void)imagePickerController:(UIImagePickerController *)picker_ didFinishPickingMediaWithInfo:(NSDictionary *)info
// 撮像終了処理(delegate)
// iOSが写真をしたら並行動作で呼び出され、この中を走っている間、メインも走り続ける
// キャンセル時はここには来ない
{
    NSLog(@"imagePickerController");
    
    // まずカメラ画面を消す
    if (isiOS5over()) { // この判定関数は自分で作ること
        [imgPicker dismissViewControllerAnimated:YES completion:NULL];
    } else {
        /// iOS4.xのみ
        [imgPicker dismissModalViewControllerAnimated:YES];
    }
    // imageはこれを含むクラスのメンバー
    image=[info objectForKey:UIImagePickerControllerOriginalImage]; // 撮影した画像を取得
    //
    NSLog(@"imagePickerController開放");
    [imgPicker release];
}


UISearchBar
検索バーは検索入力用のテキストボックスを表示&入力するビューである。 あくまで表示と入力のみなので、検索処理そのものは自分で実装する必要がある。

UISearchBar
プロパティ名属性内容
id <UISearchBarDelegate> delegateSデリゲートを設定する
NSString *placeholder Cテキストフィールド内にテキストがないときに表示される文字列
NSString *text C検索文字列(初期および現在)
NSArray *scopeButtonTitles C範囲ボタンのタイトル文字列配列
BOOL showsBookmarkButton  ブックマークボタンを表示するかどうか
BOOL showsCancelButton  キャンセルボタンを表示するかどうか
BOOL showsScopeBar  スコープバーを表示するかどうか
BOOL showsSearchResultsButton 検索結果ボタンを表示するかどうか
BOOL searchResultsButtonSelectedG=isSearchResultsButtonSelected検索結果ボタンが選ばれているかどうか
NSInteger selectedScopeButtonIndex 選択されているスコープボタンの番号
UISearchBar *sb = [[[UISearchBar alloc] init] autorelease];

sb.delegate     = self;
sb.prompt       = @"タイトル";
sb.placeholder  = @"検索ワードを入力してください";
sb.keyboardType = UIKeyboardTypeDefault;
sb.barStyle     = UIBarStyleBlack;
sb.showsCancelButton = YES;

[self.view addSubview:sb];

//テーブルのヘッダーに配置する場合
tableView.tableHeaderView = sb;


UITabBar/UITabBarItem
UITabBarは「2つ以上のボタンから1つを選ぶためのコントロールクラスである。 1つ1つのボタンのことは「アイテム」と呼ぶ。これは、アイテムをタップすることで選択を変えるために使われることが多い。 UITabBarでは、アイテム選択時に強調表示(もしくは無変化)ではなく、アニメーションによる外観変更が出来る。
UITabBar
メソッド名動作
-(void)setItems:(NSArray *)items animated:(BOOL)animatedタブバー上にアイテムを設定する(アニメーション付き)
-(void)beginCustomizingItems:(NSArray *)itemsタブバー上のモーダルビューのカスタマイズを開始する
-(BOOL)endCustomizingAnimated:(BOOL)animatedモーダルビューを破棄するときにアニメーションを使うかどうか
-(BOOL)isCustomizingタブバーがカスタマイズされているかどうか

プロパティ名属性内容
id <UITabBarDelegate> delegateSデリゲートを設定する
NSArray *itemsCタブバー上に表示するアイテム
UITabBarItem *selectedItemT選択中のアイテム

デリゲートはUITabBarDelegateプロトコルで実装する。
UITabBarDelegate
メソッド名動作
-(void)tabBar:(UITabBar *)tabBar
didSelectItem:(UITabBarItem *)item
didBeginCustomizingItems:(NSArray *)items
willBeginCustomizingItems:(NSArray *)items
didEndCustomizingItems:(NSArray *)items changed:(BOOL)changed
willEndCustomizingItems:(NSArray *)items changed:(BOOL)change

タブバーのアイテムが選択されるときに呼び出される(必須)
カスタマイズされたモーダルビューが表示された後に呼び出される
カスタマイズされたモーダルビューが表示される前に呼び出される
カスタマイズされたモーダルビューが破棄された後に呼び出される
カスタマイズされたモーダルビューが破棄される前に呼び出される

UITabBarItemはタブバーのアイテムを実装するクラスである。
メソッド名動作
-(id)initWithTabBarSystemItem:(UITabBarSystemItem)systemItem tag:(NSInteger)tag システムで用意されているアイコンでタブバーにアイテムを追加する
UITabBarSystemItem(enum値)
UITabBarSystemItemMore
UITabBarSystemItemFavorites
UITabBarSystemItemFeatured
UITabBarSystemItemTopRated
UITabBarSystemItemRecents
UITabBarSystemItemContacts
UITabBarSystemItemHistory
UITabBarSystemItemBookmarks
UITabBarSystemItemSearch
UITabBarSystemItemDownloads
UITabBarSystemItemMostRecent
UITabBarSystemItemMostViewed
-(id)initWithTitle:(NSString *)title image:(UIImage *)image tag:(NSInteger)tagユーザー作成のアイテムを追加する

プロパティ名属性内容
(NSString *)badgeValueC項目の右上角で周囲の赤い○の中に表示されるテキスト


UITabBarController
UITabBarControllerは、複数の選択項目から、同時には1つしか選択できない画面遷移を管理するコントロールである。
画面遷移という意味で、UINavigationControllerに近い。
                            サブビューコントローラー群(それぞれをアイテムと呼ぶ)
[UITabBarController]----+---UIViewController    0;要素番号(index)
                        +---UIViewController    1
                        +---UIViewController    2
                        +---UIViewController    3
UITabBarController
メソッド名動作
-(void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animatedタブバーコントローラーにルートビューコントローラーを設定する

プロパティ名属性内容
id <UITabBarControllerDelegate> delegateSデリゲートを設定する
NSArray *customizableViewControllersCこのタブバーコントローラーで管理されるサブビューコントローラー群をカスタマイズする
UINavigationController *moreNavigationControllerRMore NavigationControllerを管理するビューコントローラー
NSUInteger selectedIndex 選択中のタブアイテムの要素番号
UIViewController *selectedViewControllerS選択中のビューコントローラー
UITabBar *tabBarRコントローラーに割り付けられているタブバー
NSArray *viewControllersCタブバーで表示されているルートビューコントローラーの配列

// 画面(view1, view2, view3)をタブバーに追加する
NSArray *views = [NSArray arrayWithObjects:view1, view2, view3 nil];
[tbc setViewControllers:views animated:NO];

UIToolBar
ツールバーは1つまたは複数のボタン(アイテム)から1つを選択するコントロールクラスである。 通常全ての設定をIBで行ってしまうので、プログラム的にいじるのは有効無効を設定するくらいだろうが、 それはUIControlの仕事である。

UIToolBar
メソッド名動作
-(void)setItems:(NSArray *)items animated:(BOOL)animatedツールバー上にアイテムを設定する(アニメーション付き)

プロパティ名属性内容
UIBarStyle barStyle ツールバーの外観を指定する
UIColor *tintColorTツールバーの色を指定する
BOOL translucentSG=isTranslucentツールバーを半透明にするかどうか
NSArray *itemsCツールバーに表示する項目


UIAlertView
アラートビューとは「警告画面」のことで、Windowsで言う所のダイアログに近い。
が、画面上はそこで止まってボタンを押すまで先に進まないが、 内部処理はアラートビューを表示するとすぐ次へ進んでしまうので注意が必要である。

アラートビューはIBでは設定出来ないのでプログラムからの指定が必須となる。

UIAlertView
メソッド名動作
-(id)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate
 cancelButtonTitle:(NSString *)cancelButtonTitle
 otherButtonTitles:(NSString *)otherButtonTitles, ...
ボタンとデリゲートを持って初期化する。終端はnil
-(void)showアニメーションを使ってレシーバーを表示する
-(NSInteger)addButtonWithTitle:(NSString *)titletitleのボタンを追加する
-(NSString *)buttonTitleAtIndex:(NSInteger)buttonIndexボタン番号のtitleを返す
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animatedボタン番号のボタンを解放する(アニメーション付き)

プロパティ名 属性内容
id <UIAlertViewDelegate> delegate Sデリゲートを設定する(nil=なし)
NSString *title Cタイトル文字列
NSInteger cancelButtonIndex  キャンセルボタンのボタン番号(0~)
NSInteger firstOtherButtonIndex R第1ボタンのボタン番号
NSString *message Cタイトルより詳細な説明文を記述する
NSInteger numberOfButtons Rボタンの数を返す
BOOL visible RG=isVisible表示するかどうか

デリゲートは UIAlertViewDelegate プロトコルに準拠する。
メソッド名動作
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex ボタンが押されたときに呼び出される
initWithTitle:で設定している場合、cancelButtonTitle:が0、以下otherButtonTitlesが1~になる。
-(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex アラートビューが表示される前に呼び出される
-(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex アラートビューが画面から消えた後に呼び出される
-(void)alertViewCancel:(UIAlertView *)alertViewアラートビューがキャンセルされる前に呼び出される
-(void)didPresentAlertView:(UIAlertView *)alertViewアラートビューがユーザーに示された後に呼び出される
-(void)willPresentAlertView:(UIAlertView *)alertViewアラートビューがユーザーに示され前に呼び出される

アラートビュー表示中に電源を切ると異常動作するらしい。ただし、古い情報なので、最新のiOSではどうか不明。
  1. アラートを表示する
  2. 電源ボタンを押してスリープモードにする
  3. この時 didDismissWithButtonIndex が呼び出される;本来これはアラートビューが消えた後に呼び出されるべき
  4. スリープモードを解除
  5. アラートは閉じられていない
  6. アラートが開いている限り、電源ボタンを押すと何回でもdidDismissWithButtonIndexが呼び出される
これを避けるには、グローバルなフラグを持って制御するしかなさそう。

int pushFlag;

- 何か初期化処理のメソッド
{
    pushFlag = false;
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
// ボタンを押された時
{
    pushFlag = true;
    NSLog(@"clickedButtonAtIndex");
    NSLog(@"buttonIndex:%d", buttonIndex);
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
// アラートビューが画面から消えた後に呼び出される
{
    if (pushFlag) { // ボタンを押されてアラートビューを閉じるときのみ正規の処理とみなす
        NSLog(@"didDismissWithButtonIndex");
        NSLog(@"buttonIndex:%d", buttonIndex);
        pushFlag = false;
    }
}


UIActionSheet
アクションシートはダイアログの一種で、iPhone/iPodでは画面の下から「にゅっ」っと、 iPadでは画面の真ん中に出てきて、ボタンの選択を求める。
アクションシート外の画面をタッチすると自動的に閉じられる。そこがUIAlearViewとの最大の違いである。

アクションシートもIBでは設定出来ないのでプログラムからの指定が必須となる。

UIActionSheet
メソッド名動作
-(id)initWithTitle:(NSString *)title delegate:(id <UIActionSheetDelegate >)delegate cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... アクションシートのインスタンスを作成する
-(NSInteger)addButtonWithTitle:(NSString *)title指定したタイトルでボタンを追加する
-(NSString *)buttonTitleAtIndex:(NSInteger)buttonIndex指定したインデックスのボタンのタイトルを返す
-(void)showInView:(UIView *)view指定したビューからレシーバを表示する
-(void)showFromTabBar:(UITabBar *)view指定したタブバーからレシーバを表示する
-(void)showFromToolbar:(UIToolbar *)view指定したツールバーからレシーバを表示する
-(void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated 指定されたバーボタン項目から始まるアクションシートを表示する
-(void)showFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated 指定されたビューから始まるアクションシートを示す
-(void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated ボタンを押したことにしてアクションシートを消す

プロパティ名属性内容
id <UIActionSheetDelegate> delegate デリゲートを設定する
NSString *titleCタイトル文字列を設定する
NSInteger numberOfButtons Rアクションシート上のボタン数を返す
NSInteger cancelButtonIndex  キャンセルボタンの番号を返す
NSInteger destructiveButtonIndex 否定的なボタンの番号を指定する
NSInteger firstOtherButtonIndex R一番目のボタンの番号を返す
UIActionSheetStyle actionSheetStyle スタイルを指定する
UIActionSheetStyle(enum値)
UIActionSheetStyleAutomatic ボタンバー(があればその)外観になる。なければデフォルトと同じ
UIActionSheetStyleDefault デフォルト
UIActionSheetStyleBlackTranslucent 黒い半透明のスタイル
UIActionSheetStyleBlackOpaque 黒い不透明なスタイル
BOOL visibleRG=isVisible表示されているかどうか
注: アプリケーションがバックグラウンドに移行するとき、アクションシートは自動的に閉じられないらしい。


デリゲートは UIActionSheetDelegateプロトコルに準拠する。 直接プログラムで記述方法を書く。
// ヘッダー側
@interface CamViewController : UIViewController <UIActionSheetDelegate>
{
}

// アクションシートのインスタンス
- (IBAction)showCamSheet;

@end
// 本体側
- (IBAction)showCameraSheet
{
    // アクションシートを作る
    UIActionSheet*  sheet;
    sheet = [[UIActionSheet alloc] 
               initWithTitle:@"Select Soruce Type" // タイトル文字列
                    delegate:self                  // デリゲート処理の存在メソッド(ここでは自身の中)
           cancelButtonTitle:@"Cancel"             // キャンセルボタンの文字列
      destructiveButtonTitle:nil                   // 否定的ボタンの文字列
           otherButtonTitles:@"Photo Library", @"Camera", @"Saved Photos", nil  // 他のボタンの文字列(可変引数なので必要なだけ)
    ];
    [sheet autorelease];

    // アクションシートを表示する
    [sheet showInView:self.view];
}
showCamSheetでは、アクションシートの表示を行っている。 まず、UIActionSheetクラスのインスタンスを作る。 ボタンは可変引数で複数指定できる。
actionSheet:clickedButtonAtIndex:メソッドはボタンをクリックしたときに呼び出される。
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
// 閉じるときの処理(デリゲート)
{
    // ボタンインデックスをチェックする
    // buttonIndexは押されたボタンの番号;0~cancelButtonTitle、destructiveButtonTitle、otherButtonTitlesの数-1
    switch (buttonIndex) {
        default:
            break;
        case 0:
            ~
            break;
        case 1:
            ~
            break;
        case 2:
            ~
            break;
    }
    ~
}