AssetsLibraryの勉強:フォトライブラリの最新の画像を取得

「フォトライブラリの最新の画像を取得する」というボタンをiOSに設置したくて奮闘中。
とりあえず、なんとなくAssetsLibraryのことがわかってきた。

■AssetsLibrary
→本体。こいつでやることは特に無い。
AssetsGroupを取ってくるくらい。
アルバムの新規作成はできる気がしたが未検証

取り方は下記

                                                                                                                • -

// まず、グループ列挙時の関数を定義
void (^groupBlock)( ALAssetsGroup*, BOOL* ) = ^( ALAssetsGroup* group, BOOL* stop ){
if( group == nil ) { return; }
[self.groups addObject:group];
//今回はこの後でAssetsも取得するので。
[self performSelectorOnMainThread:@selector( getFirstAssets ) withObject:nil waitUntilDone:NO];
};

// エラー関数定義
void (^failureBlock)( NSError* ) = ^( NSError* error ){ NSLog( @"Group enumurate error: %@", error ); };

//アルバム情報の取得
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:groupBlock failureBlock:failureBlock];

                                                                                                                • -

enumerateGroupsWithTypes:usingBlock:failureBlock: のusingBlockが起動するタイミングが良くわかっていないが、
こいつが入ってるメソッドの終了時な気がする。
ので、enumerateGroupsWithTypes:... の直後にgroupを取得するような関数を書くと失敗する。


■AssetsGroup
→アルバム。この中に画像がいっぱい入ってる。
Groupの中から、Assetを取り出す。

取り方は下記

                                                                                                              • -
  • (void) getFirstAssets{

//最初のグループを取得
ALAssetsGroup *group = [self.groups objectAtIndex:0];

//Assetsを取得
[group enumerateAssetsUsingBlock:^( ALAsset *result, NSUInteger index, BOOL *stop ){
if( result == nil ) { return; }
NSString* type = [result valueForProperty:ALAssetPropertyType];
if( [type isEqualToString:ALAssetTypeVideo] ) { return; } //写真のみにする
[self.assets addObject:result];
}];
}

                                                                                                              • -

Groupsの時と同様、enumrateAssetsUsingBlock: の関数の呼び出しタイミングがよくわかっていないが、
こいつが入ってるメソッドの終了時な気がする。


■Assets
→画像(とか動画とか)のオブジェクト。
日付とかは取れるらしいが今回は特に使わなかった。今回は「こいつが画像なのか?動画なのか?を一応利用。
実際に画像データ(UIImageとか)を扱うには、assetの中からassetRepresentationを取り出す必要がある。
ちなみに、AssetsLibraryからURLを指定することでassetを直接取り出すこともできるっぽい。

assetRepresentationの取得方法は下記

                                                                                                                        • -

ALAsset* asset = [self.assets lastObject];
if( asset == nil ) { return; }
ALAssetRepresentation* rep = [asset defaultRepresentation];

                                                                                                                        • -

defaultじゃないのは何があるのか、とかそういうことはまだ不明


■AssetRepresentation
→実際のデータが詰まってる。
UIImageとかを取ってくるにはこれを使う

こんな感じ

                                                                                                                        • -

UIImage* image = [UIImage imageWithCGImage:[rep fullScreenImage] scale:[rep scale] orientation:( UIImageOrientation )[rep orientation]];
_imageView.image = image;
-------------------------------------------------------------



しかし、最後のデータを取得したいだけなのに、Library,Groups,Assets,Asset,AssetRepresentationといっぱい取得するのはなんだか無駄な気がするので、なんとかスマートに取得できないか奮闘中。

===========================

追記

いろいろ奮闘してみた。
・画面の表示時ではなく、ボタン押下時に最新の画像を取得
・Assetはすべてを取得せず、最後の一枚だけを正確に取得
また、各種enumerationメソッドは最後に result=nil のデータが来る、ということがわかったので、
callback関数を定義することもできた。

                                                                              • -

//最新の画像を取得

  • (IBAction)useBlandNewImage:(id)sender {


self.assetLibrary = [[ALAssetsLibrary alloc] init];
self.groups = [[NSMutableArray alloc] init];

//関数を先に定義
void (^failureBlock)( NSError* ) = ^( NSError* error ){ NSLog( @"Error in enumerateGroup: %@", error ); };
void (^groupBlock)( ALAssetsGroup*, BOOL* ) = ^( ALAssetsGroup* group, BOOL* stop ){
if(group){
[self.groups addObject:group];
}else{
//すべて取得し終わったら、最初のグループの最後のassetを取得
ALAssetsGroup *group = [self.groups objectAtIndex:0];
NSMutableIndexSet *indexSet = [NSMutableIndexSet new];
[indexSet addIndex:[group numberOfAssets]-1];
[group enumerateAssetsAtIndexes:indexSet options:nil usingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop) {
if(asset){
//一つしかない
ALAssetRepresentation *rep = [asset defaultRepresentation];
UIImage* image = [UIImage imageWithCGImage:[rep fullScreenImage] scale:[rep scale] orientation:( UIImageOrientation )[rep orientation]];

_imageView.image = image;
}else{
[self analizeImage];
}
}];
}
};

//画像ゲット
[self.assetLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:groupBlock failureBlock:failureBlock];

}

                                                                              • -