ObjecTips

Swift & Objective-C で iOS とか macOS とか

カメラで撮影した写真と動画を Photos.framework でライブラリに保存する

撮影は UIImagePickerController にお任せして撮影後のデータを Photos で保存する実装方法。

まず UIImagePickerControllersourceType でカメラ撮影を指定。
デフォルトのままだと写真撮影しかできないので、カメラ撮影で利用可能な形式を全て設定して動画撮影もできる様に mediaTypes を設定する。
これで写真と動画の撮影はOK

    UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.sourceType = sourceType;
    picker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:sourceType];
    picker.delegate = self;
    [self presentViewController:picker animated:YES completion:nil];

撮影したデータの取得は UIImagePickerControllerDelegate のデリゲートメソッドで行う

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info

写真撮影時は info に UIImagePickerControllerOriginalImage キーで UIImage で画像データが入ってきて、動画撮影時には UIImagePickerControllerMediaURLNSURL で動画ファイルのURLが入ってくるという違いがあるので撮影方法によって条件分岐して処理する必要がある。
どちらで撮影されたかは info から UIImagePickerControllerMediaType キーで取得して判定できる。

    NSString *mediaType = info[UIImagePickerControllerMediaType];
    if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
    }
    else if ([mediaType isEqualToString:(NSString *)kUTTypeMovie]) {
    }

なおここの kUTTypeImagekUTTypeMovie のキーを使うために MobileCoreServices.framework も import しておく必要がある。
分岐の後、画像であれば PHAssetChangeRequest

+ (instancetype)creationRequestForAssetFromImage:(UIImage *)image;

動画ファイルのURLであれば

+ (nullable instancetype)creationRequestForAssetFromVideoAtFileURL:(NSURL *)fileURL;

これらのメソッドを使ってライブラリへのデータ保存を行う。

PHAssetChangeRequest は若干変わった利用方法になっていて、以下のように PHPhotoLibrary の変更を行うブロック内でこのインスタンスを作成すると PHPhotoLibrary が勝手に保存処理を行ってくれる。
目に見えて解りやすい save, write などの直接的なメソッド呼び出しでの保存ではないのでちょっと注意。

    PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
    [library performChanges:^{
            [PHAssetChangeRequest creationRequestForAssetFromImage:image];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
    }];

コード全体は以下のようになる