199

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

4

15 回答 15

417

您可以使用此功能:

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

如果您想在保存完成时收到通知,您只需要completionTargetcompletionSelectorcontextInfoUIImage,否则您可以传入nil.

参见官方文档UIImageWriteToSavedPhotosAlbum()

于 2008-10-07T15:32:02.110 回答
63

在 iOS 9.0 中已弃用。

使用 iOS 4.0+ AssetsLibrary 框架的 UIImageWriteToSavedPhotosAlbum 方法比 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];
于 2010-09-21T13:53:03.990 回答
32

最简单的方法是:

UIImageWriteToSavedPhotosAlbum(myUIImage, nil, nil, nil);

对于Swift,可以参考使用 swift 保存到 iOS 照片库

于 2013-12-24T07:36:57.473 回答
13

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

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

否则,您将因以下错误而崩溃:

[NSInvocation setArgument:atIndex:]: index (2) out of bounds [-1, 1]

于 2013-04-02T03:35:26.343 回答
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);
        }
}

抱歉,错字有点匆忙,但你明白了

于 2010-03-30T02:16:53.373 回答
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);
   }
}
于 2013-08-13T23:01:51.243 回答
4

斯威夫特

    // 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.
            }
    }
于 2015-03-18T21:32:30.117 回答
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");
        }
    }];
}
于 2015-10-06T04:58:29.637 回答
3

斯威夫特 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!")
    }
}
于 2019-01-18T08:44:48.247 回答
1

我的最后一个答案会做到这一点..

对于您要保存的每个图像,将其添加到 NSMutableArray

    //in the .h file put:

NSMutableArray *myPhotoArray;


///then in the .m

- (void) viewDidLoad {

 myPhotoArray = [[NSMutableArray alloc]init];



}

//However Your getting images

- (void) someOtherMethod { 

 UIImage *someImage = [your prefered method of using this];
[myPhotoArray addObject:someImage];

}

-(void) saveMePlease {

//Loop through the array here
for (int i=0:i<[myPhotoArray count]:i++){
         NSString *file = [myPhotoArray 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);
        }
}
于 2010-05-20T01:33:32.690 回答
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];
}
于 2011-03-11T11:46:05.020 回答
1

根据上面的一些答案,我为此创建了一个 UIImageView 类别。

头文件:

@interface UIImageView (SaveImage) <UIActionSheetDelegate>
- (void)addHoldToSave;
@end

执行

@implementation UIImageView (SaveImage)
- (void)addHoldToSave{
    UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
    longPress.minimumPressDuration = 1.0f;
    [self addGestureRecognizer:longPress];
}

-  (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
    if (sender.state == UIGestureRecognizerStateEnded) {

        UIActionSheet* _attachmentMenuSheet = [[UIActionSheet alloc] initWithTitle:nil
                                                                          delegate:self
                                                                 cancelButtonTitle:@"Cancel"
                                                            destructiveButtonTitle:nil
                                                                 otherButtonTitles:@"Save Image", nil];
        [_attachmentMenuSheet showInView:[[UIView alloc] initWithFrame:self.frame]];
    }
    else if (sender.state == UIGestureRecognizerStateBegan){
        //Do nothing
    }
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
    if  (buttonIndex == 0) {
        UIImageWriteToSavedPhotosAlbum(self.image, nil,nil, nil);
    }
}


@end

现在只需在你的 imageview 上调用这个函数:

[self.imageView addHoldToSave];

您可以选择更改 minimumPressDuration 参数。

于 2015-07-20T08:38:00.623 回答
1

斯威夫特 2.2

UIImageWriteToSavedPhotosAlbum(image: UIImage, _ completionTarget: AnyObject?, _ completionSelector: Selector, _ contextInfo: UnsafeMutablePointer<Void>)

如果您不想在图像保存完成时收到通知,那么您可以在completionTargetcompletionSelectorcontextInfo参数中传递 nil。

例子:

UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.imageSaved(_:didFinishSavingWithError:contextInfo:)), nil)

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

这里要注意的重要一点是,您观察图像保存的方法应该具有这 3 个参数,否则您将遇到 NSInvocation 错误。

希望能帮助到你。

于 2016-04-24T04:56:26.983 回答
0

你可以用这个

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   UIImageWriteToSavedPhotosAlbum(img.image, nil, nil, nil);
});
于 2014-01-22T11:21:51.693 回答
0

对于 Swift 5.0

我使用此代码将图像复制到我的应用程序创建的相册中;当我想复制图像文件时,我调用“startSavingPhotoAlbume()”函数。首先,我从 App 文件夹中获取 UIImage,然后将其保存到相册。因为它无关紧要,所以我没有展示如何从 App 文件夹中读取图像。

var saveToPhotoAlbumCounter = 0



func startSavingPhotoAlbume(){
    saveToPhotoAlbumCounter = 0
    saveToPhotoAlbume()
}

func saveToPhotoAlbume(){  
    let image = loadImageFile(fileName: imagefileList[saveToPhotoAlbumCounter], folderName: folderName)
    UIImageWriteToSavedPhotosAlbum(image!, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
}

@objc func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
    if (error != nil) {
        print("ptoto albume savin error for \(imageFileList[saveToPhotoAlbumCounter])")
    } else {
        
        if saveToPhotoAlbumCounter < imageFileList.count - 1 {
            saveToPhotoAlbumCounter += 1
            saveToPhotoAlbume()
        } else {
            print("saveToPhotoAlbume is finished with \(saveToPhotoAlbumCounter) files")
        }
    }
}
于 2020-09-24T12:43:08.147 回答