Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
56
Help us understand the problem. What is going on with this article?
@taketomato

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

More than 5 years have passed since last update.

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 特集

56
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
jrits
信頼と魅力のある先進のITをもとに、お客様のワークスタイル・イノベーションの実現を目指します。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
56
Help us understand the problem. What is going on with this article?