使用照片框架将图像保存到照片库

13

每次我试图使用照片框架保存图像时,我的应用程序都会崩溃。

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{

      _mChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[info valueForKey:UIImagePickerControllerOriginalImage]];

      [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{

      _mChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[info valueForKey:UIImagePickerControllerOriginalImage]];

      } completionHandler:^(BOOL success, NSError *error) {

          if (success) {

              PHObjectPlaceholder *assetPlaceholder = _mChangeRequest.placeholderForCreatedAsset;
          }
          else {

             NSLog(@"write error : %@",error);
          }
    }];
}

crash : NSInternalInconsistencyException', reason: 'This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]'
4个回答

43

您需要做的就是触发一个创建请求。正如错误提示所说,您只能在 performChanges 块内部访问更改请求。

因此,要保存图像,您可以执行以下操作:

[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
    [PHAssetChangeRequest creationRequestForAssetFromImage:[info valueForKey:UIImagePickerControllerOriginalImage]];
} completionHandler:^(BOOL success, NSError *error) {
    if (success) {
         NSLog(@"Success");
    }
    else {
        NSLog(@"write error : %@",error);
    }
}];

如果您需要对新创建的资产的占位符进行操作,您可以在同一个performChanges块内访问它:

PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[info valueForKey:UIImagePickerControllerOriginalImage]];
PHObjectPlaceholder *assetPlaceholder = changeRequest.placeholderForCreatedAsset;

3
然后如何获取该图像的URL - Deepraj Chowrasia

4
在Swift 3中,我这样做可以将视频保存到库中。
if mediaType.isEqual(to: (kUTTypeMovie as NSString) as String) {
    if let videoURL = info[UIImagePickerControllerMediaURL] as? URL {
        PHPhotoLibrary.shared().performChanges({
            _ = PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: videoURL)
        }, completionHandler: { (success, error) in
            if success {
                print("ok")
                let videoData = NSData(contentsOf: videoURL)
                // use videoData here if needed...
                if let posterImage = self.firstFrame(videoURL: videoURL) {
                    self.imageView.image = posterImage
                }
                picker.dismiss(animated: true) { () -> Void in
                }
            } else {
                print(error?.localizedDescription)
            }
        })
    }
}

哇,谢谢!这个语法对我来说很奇怪。为什么需要 in 关键字呢?还有定义在函数块内的参数。 - MichaelGofron

3
以下是使用UIImageWriteToSavedPhotosAlbum函数将图像写入照片库的代码示例:
- (void)saveImage:(UIImage *)image {
    UIImageWriteToSavedPhotosAlbum(self.image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
{
    if (!error) {
        // saved successfully

        PHFetchOptions *fetchOptions = [PHFetchOptions new];
        fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
        PHAsset *asset = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:fetchOptions].firstObject;
        if (asset != nil) {
            // here you can use asset of your image
        }
    } else {
        NSLog(@"save image error: %@", error);
    }
}

不要忘记在您的Info.plist中添加一个键值对Privacy - Camera Usage Description,并描述其使用方式。

UIImageWriteToSavedPhotosAlbum 不是 PhotoKit 的一部分... - benc

2
  1. 删除代码的第三行。
  2. 验证_mChangeRequest是__block变量。
  3. 编译并运行。

这样你就可以在照片应用程序中看到图像了。

你可能需要修改代码,如下所示...

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info {
    __block PHAssetChangeRequest *_mChangeRequest = nil;
    [[PHPhotoLibrary sharedPhotoLibrary]
            performChanges:^{
                UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
                _mChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
            }, completionHandler :^(BOOL success, NSError *error) {
        if (success) {
            PHObjectPlaceholder *assetPlaceholder = _mChangeRequest.placeholderForCreatedAsset;
        } else {
            NSLog(@"write error : %@", error);
        }
    }];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接