「PhotoGroupViewController.m」に以下のようにコードを追加します。
#import "PhotoSelectViewController.h" #pragma mark Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { PhotoSelectViewController *controller = [[PhotoSelectViewController alloc] init]; controller.delegate = self; controller.group = [groups objectAtIndex:indexPath.row]; [self.navigationController pushViewController:controller animated:YES]; [controller release]; }
次に、[PhotoSelectViewController]をXcodeのグループとファイルに新規作成します。
#import "PhotoViewController.h" @interface PhotoSelectViewController : UITableViewController<PhotoViewControllerDelegate> { id delegate; ALAssetsGroup *group; @private NSMutableArray *photos; } @property (nonatomic, assign) id delegate; @property (nonatomic, retain) ALAssetsGroup *group; @end
メンバ変数groupは、呼び出し元のPhotoGroupViewControllerのテーブルから選択された行のALAssetsGroupを保持します。
メンバ変数photosは、AssetsLibraryフレームワークで定義されたALAssetクラスの集合を保持します。ALAssetクラスはフォトライブラリ内の静止画、または動画を保持しています。
#import "PhotoSelectViewController.h" @implementation PhotoSelectViewController @synthesize delegate; @synthesize group; #pragma mark Rotation support - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } #pragma mark View lifecycle - (void)viewDidLoad { [super viewDidLoad]; [self.navigationItem setTitle:@"フォト選択"]; [self performSelectorInBackground:@selector(searchPhotos) withObject:nil]; } - (void)searchPhotos { photos = [[NSMutableArray alloc] init]; // フォトライブラリから取得した写真を「photos」に追加 void (^assetBlock)(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop) { if(result != nil) { if(![photos containsObject:result]) { // ALAssetのタイプが「写真」を追加 if([[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) { [photos addObject:result]; } } } }; // フォトライブラリへアクセスし、引数のブロックを実行 [group enumerateAssetsUsingBlock:assetBlock]; [self.tableView reloadData]; } // テーブル指定行の画像データを取得 - (UIImage *)getPhotoImage:(NSUInteger)index { return [UIImage imageWithCGImage: [[(ALAsset *)[photos objectAtIndex:index] defaultRepresentation] fullScreenImage]]; } // テーブル指定行のメタデータを取得 - (NSDictionary *)getPhotoMetaData:(NSUInteger)index { NSDictionary *metaData = [[(ALAsset *)[photos objectAtIndex:index] defaultRepresentation] metadata]; return [metaData objectForKey:(NSString *)kCGImagePropertyExifDictionary]; } #pragma mark Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [photos count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; UIImage *image = [self getPhotoImage:indexPath.row]; NSDictionary *metadata = [self getPhotoMetaData:indexPath.row]; NSString *title = [metadata objectForKey:(NSString *)kCGImagePropertyExifUserComment]; cell.imageView.image = image; cell.textLabel.text = [NSString stringWithFormat:@"%@", title]; return cell; } #pragma mark Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [self photoSelect:[self getPhotoImage:indexPath.row]]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 300; } #pragma mark PhotoViewControllerDelegate Methods - (void)photoSelect:(UIImage *)image { [delegate photoSelect:image]; } - (void)photoSelectCancel { [delegate photoSelectCancel]; } #pragma mark Memory management - (void)dealloc { [super dealloc]; } @end
「searchPhotos」メソッドでは、「assetBlock」というブロック構文をALAssetGroupのenumerateAssetsUsingBlockメソッドに渡すことでグループ内の写真データをphotos変数に追加しています。
ALAssetクラスは写真だけでなく動画データも保持しており、valueForPropertyメソッドの引数にALAssetPropertyTypeを渡すことでAssetの種類が取得できます。Assetの種類には以下の3つがあります。
ValueForPropertyメソッドでは上記以外にも「位置情報」や「撮影日」などが必要に応じて取得できます。ALAssetクラスの公式リファレンスにも詳細が記載されています。
「getPhotoImage : index」メソッドでは、photos配列のindexを指定することで、ALAssetからテーブル選択行の画像データ(UIImage)を取得しています。
ALAssetのdefaultRepresentationメソッドで実際のメタデータや画像データを保持したオブジェクトを取得し、その中からfullScreenImageメソッドでフォトライブリに保存されたフル画像を取得しています。
「getPhotoMetaData : index」メソッドでは、getPhotoImageメソッドと同様に、defaultRepresentationメソッドを使用してメタデータを取得しています。
さらに、このメタデータの中のExif情報のみを、「ImageIO」フレームワークで定義された「kCGImagePropertyExifDictionary」という定数で取得しています。
「tableView : cellForRowAtIndexPath : indexPath」メソッドでは、メンバ変数photosから行ごとのALAssetを取得し、写真画像・写真タイトル(Exif情報)を取得し、セルにセットしています。
写真タイトルは「kCGImagePropertyExifUserComment」というコメントを表した定数を使用していますが、これは後ほど写真タイトルをセットする実装を行う際に、この定数を使用しているためです。
ここまで実装が完了したら、ビルドして実行してみましょう。「グループ選択」画面から行を選択すると「フォト選択」画面が現れ、フォトライブラリから取得した写真が一覧で表示されます。
次ページでは、写真がテーブルから選択された後の処理として、読み込んだ画像にも絵を描けるようにする機能とExif情報に絵のタイトルを設定する機能を実装し、アプリを完成します。
Copyright © ITmedia, Inc. All Rights Reserved.