如何将图片保存到iPhone照片库?

199

我该怎么做才能将我的程序生成的图片(可能来自相机,也可能不是)保存到iPhone系统照片库中?


你可以查看这段代码。祝你有美好的一天! - Celil Bozkurt
15个回答

417

您可以使用此函数:

UIImageWriteToSavedPhotosAlbum(UIImage *image, 
                               id completionTarget, 
                               SEL completionSelector, 
                               void *contextInfo);

如果您想在UIImage保存完成时得到通知,那么只需要使用completionTargetcompletionSelectorcontextInfo,否则可以传入nil

请参阅官方文档有关UIImageWriteToSavedPhotosAlbum()的说明


只返回翻译的文本:取得准确答案加1拿+1作为正确答案 - Niru Mukund Shah
嗨,感谢您提供的出色解决方案。我有一个疑问,当我们保存图像到照片库时,如何避免重复?提前致谢。 - Naresh
如果您想以更好的质量保存,请参阅此链接:https://dev59.com/vknSa4cB1Zd3GeqPLzW4 - eonil
请记得在您的info.plist文件中添加键“Privacy - Photo Library Usage Description”。 - Leo
9
从iOS 11开始,为了保存用户相册中的照片,您现在需要添加“隐私-照片库添加使用说明”。 - horsejockey
1
如何为保存的图像命名? - Priyal

63

iOS 9.0 中已弃用。

在 iOS 4.0+ 的 AssetsLibrary 框架中,有一种比 UIImageWriteToSavedPhotosAlbum 更快的方法来实现它。

    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

    [library writeImageToSavedPhotosAlbum:[image CGImage] orientation:(ALAssetOrientation)[image imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
    if (error) {
    // TODO: error handling
    } else {
    // TODO: success handling
    }
}];
[library release];

1
有没有一种方法可以将任意元数据与照片一起保存? - zakdances
3
我尝试使用ALAssetsLibrary进行保存,但它花费的时间与使用UIImageWriteToSavedPhotosAlbum保存的时间一样长。 - Hlung
这会导致相机卡住 :( 我猜它不支持后台? - Hlung
这个更加简洁,因为你可以使用块来处理完成。 - jpswain
5
我正在使用这段代码,并包含这个框架 #import <AssetsLibrary/AssetsLibrary.h> 而不是 AVFoundation。难道答案不应该被编辑吗?@Denis - Julian Osorio
很好,但在iOS 9 SDK中已被弃用。 - eonil

33

3
我很喜欢你的 Stack Overflow 用户个人资料头像。那个 Xcode 图标很酷。 - Supertecnoboff
1
非常简单,非常容易! - Septronic

13

需要记住的一件事:如果您使用回调函数,请确保您的选择器符合以下形式:

- (void) image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo;

否则,您将遇到以下错误而崩溃:[NSInvocation setArgument:atIndex:]: index (2) out of bounds [-1, 1]

10

只需像这样从数组中传递图像即可:

-(void) saveMePlease {

//Loop through the array here
for (int i=0:i<[arrayOfPhotos count]:i++){
         NSString *file = [arrayOfPhotos objectAtIndex:i];
         NSString *path = [get the path of the image like you would in DOCS FOLDER or whatever];
         NSString *imagePath = [path stringByAppendingString:file];
         UIImage *image = [[[UIImage alloc] initWithContentsOfFile:imagePath]autorelease];

         //Now it will do this for each photo in the array
         UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
        }
}

抱歉有些错别字,我是匆忙完成的,但你应该能理解我的意思。


使用这种方法会错过一些照片,我已经尝试过了。正确的做法是使用完成选择器的回调函数。 - SamChen
1
我们可以使用自定义名称保存图片吗? - BhavikKama
不应该使用for循环来处理这个问题,因为它会导致竞态条件并引发崩溃。 - saurabh

4
以下函数可以正常工作。您可以从这里复制并粘贴到相应位置...
-(void)savePhotoToAlbum:(UIImage*)imageToSave {

    CGImageRef imageRef = imageToSave.CGImage;
    NSDictionary *metadata = [NSDictionary new]; // you can add
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

    [library writeImageToSavedPhotosAlbum:imageRef metadata:metadata completionBlock:^(NSURL *assetURL,NSError *error){
        if(error) {
            NSLog(@"Image save eror");
        }
    }];
}

4
Swift 中:
    // Save it to the camera roll / saved photo album
    // UIImageWriteToSavedPhotosAlbum(self.myUIImageView.image, nil, nil, nil) or 
    UIImageWriteToSavedPhotosAlbum(self.myUIImageView.image, self, "image:didFinishSavingWithError:contextInfo:", nil)

    func image(image: UIImage!, didFinishSavingWithError error: NSError!, contextInfo: AnyObject!) {
            if (error != nil) {
                // Something wrong happened.
            } else {
                // Everything is alright.
            }
    }

是的...很好...但是在保存图像后,我想从相册加载图像...怎么做? - Bhavin Bhadani

4

保存一组照片时,不要使用for循环,可以采用以下方法:

-(void)saveToAlbum{
   [self performSelectorInBackground:@selector(startSavingToAlbum) withObject:nil];
}
-(void)startSavingToAlbum{
   currentSavingIndex = 0;
   UIImage* img = arrayOfPhoto[currentSavingIndex];//get your image
   UIImageWriteToSavedPhotosAlbum(img, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
- (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo{ //can also handle error message as well
   currentSavingIndex ++;
   if (currentSavingIndex >= arrayOfPhoto.count) {
       return; //notify the user it's done.
   }
   else
   {
       UIImage* img = arrayOfPhoto[currentSavingIndex];
       UIImageWriteToSavedPhotosAlbum(img, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
   }
}

3

Swift 4

func writeImage(image: UIImage) {
    UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.finishWriteImage), nil)
}

@objc private func finishWriteImage(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
    if (error != nil) {
        // Something wrong happened.
        print("error occurred: \(String(describing: error))")
    } else {
        // Everything is alright.
        print("saved success!")
    }
}

1
homeDirectoryPath = NSHomeDirectory();
unexpandedPath = [homeDirectoryPath stringByAppendingString:@"/Pictures/"];

folderPath = [NSString pathWithComponents:[NSArray arrayWithObjects:[NSString stringWithString:[unexpandedPath stringByExpandingTildeInPath]], nil]];

unexpandedImagePath = [folderPath stringByAppendingString:@"/image.png"];

imagePath = [NSString pathWithComponents:[NSArray arrayWithObjects:[NSString stringWithString:[unexpandedImagePath stringByExpandingTildeInPath]], nil]];

if (![[NSFileManager defaultManager] fileExistsAtPath:folderPath isDirectory:NULL]) {
    [[NSFileManager defaultManager] createDirectoryAtPath:folderPath attributes:nil];
}

这个答案不正确,因为它没有将图像保存到系统照片库中,而是保存在沙盒中。 - Evan

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