57
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Photos Framework を使って写真.appと画像をやりとりする

Last updated at Posted at 2014-12-17

iOS8で Photos Framework が追加されました。
Photos Framework は「写真.app」や「iCloud」の写真/ビデオに対し、読み書きやプロパティの編集、変更の監視などができます。
App Extensionが追加されたのもあり、写真やビデオを複数のアプリで扱うための機能が用意されています。

写真.appと画像をやりとりするサンプルを作成してみました

Photos Framework では、 主に3つの階層があってその上でデータをやりとりします。
基本的な読み書きでは、PHAssetCollecitonPHAssetを扱うことになります。

クラス なにを扱うのか
PHCollectionList PHAssetCollectionの集まり
PHAssetCollection カメラロール自体やユーザ作成のフォルダ、モーメントの年など
PHAsset 写真やビデオ自体

アルバムから画像を取得して UIImageView に表示する

- (void)readImage {
    // PHAssetCollection を取得します
    PHAssestCollection * myAlbum = [self getMyAlbum];

    // PHAsset をフェッチします
    PHFetchResult *assets = [PHAsset fetchAssetsInAssetCollection:myAlbum options:nil];

    // フェッチ結果から assets を取り出します
    NSArray * assetArray = [self getAssets:assets];
    
    // asset を使って、UIImageView をランダムに更新します
    [self updateImageViewWithAsset:assetArray[arc4random() % assets.count]];
}

- (PHAssetCollection *)getMyAlbum {
        // ユーザ作成のアルバム一覧を指定して、PHAssetCollection をフェッチします
    PHFetchResult *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum
                                                                               subtype:PHAssetCollectionSubtypeAlbumRegular
                                                                               options:nil];
    
    // [My Album]の AssetCollection を取得します
    __block PHAssetCollection * myAlbum;
    [assetCollections enumerateObjectsUsingBlock:^(PHAssetCollection *album, NSUInteger idx, BOOL *stop) {
        if ([album.localizedTitle isEqualToString:@"My Album"]) {
            myAlbum = album;
            *stop = YES;
        }
    }];
    
    return myAlbum;
}

- (NSArray *)getAssets:(PHFetchResult *)fetch {
    // フェッチ結果を配列に格納します
    __block NSMutableArray * assetArray = NSMutableArray.new;
    [fetch enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {
        [assetArray addObject:asset];
    }];
    return assetArray;
}

- (void)updateImageViewWithAsset:(PHAsset *)asset {
    typeof(self) __weak wself = self;
    [[PHImageManager defaultManager] requestImageForAsset:asset
                                               targetSize:CGSizeMake(300,300)
                                              contentMode:PHImageContentModeAspectFill
                                                  options:nil
                                            resultHandler:^(UIImage *result, NSDictionary *info) {
                                                if (result) {
                                                    // imageVivew を更新します
                                                    wself.imageView.image = result;
                                                }
                                            }];
}

アルバムに画像を保存する

「写真.app」へ変更を要求する場合は、xxxChangeRequestというクラスを使用します。
保存するときに、identifierが取得できます。これを使って画像を取り出すこともできます。

- (void)addNewAssetWithImage:(UIImage *)image toAlbum:(PHAssetCollection *)album
{
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        // PHAssetChangeRequest を作ります
        PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
        
        // PHAssetCollectionChangeRequest を作ります
        PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:album];
        
        // placeholder を取得して、PHAssetCollection に asset を追加します
        PHObjectPlaceholder * placeHolder = [createAssetRequest placeholderForCreatedAsset];
        [albumChangeRequest addAssets:@[ placeHolder ]];
        
        // placeholder から取得できる identifier を
        // 保存しておくと後から画像を一意に取得することができます
        NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:placeHolder.localIdentifier forKey:kAssetIdentifier];
        [defaults synchronize];
        
    } completionHandler:^(BOOL success, NSError *error) {
        NSLog(@"Finished adding asset. %@", (success ? @"Success" : error));
    }];
}

保存した画像をアルバムから Identifier で読み込む

getAssets:updateImageViewWithAsset:は上で記述したメソッドです。

- (void)readImageWidthIdentifier {
    // Identifier を指定して PHAsset をフェッチします
    NSString * identifier = [[NSUserDefaults standardUserDefaults]objectForKey:kAssetIdentifier];
    PHFetchResult *assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[identifier] options:nil];
    
    // assets を取り出します
    NSArray * assetArray = [self getAssets:assets];
    
    // UIImageView を更新します
    [self updateImageViewWithAsset:assetArray.lastObject];
}

ALAssestLibrary との違いとして、フェッチ結果の取り出しが同期になっているのが使いやすく感じました。
もっと使いこなせるようになっていきたいですね。

サンプルコード

参考URL

Photos Framework 公式ドキュメント
Developers.IO PhotoKit 特集

57
55
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
55

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?