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

时间:2022-01-04 15:49:35

What do I need to do to save an image my program has generated (possibly from the camera, possibly not) to the system photo library on the iPhone?

我需要做什么来保存我的程序生成的图像(可能是从摄像头生成的,也可能不是)到iPhone上的系统照片库?

13 个解决方案

#1


395  

You can use this function:

你可以使用这个功能:

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

You only need completionTarget, completionSelector and contextInfo if you want to be notified when the UIImage is done saving, otherwise you can pass in nil.

如果你想在UIImage完成保存时得到通知,你只需要completionTarget, completionSelector和contextInfo,否则你可以传入nil。

See the official documentation for UIImageWriteToSavedPhotosAlbum().

参见UIImageWriteToSavedPhotosAlbum()的官方文档。

#2


63  

Deprecated in iOS 9.0.

在iOS 9.0中弃用。

There`s much more fast then UIImageWriteToSavedPhotosAlbum way to do it using iOS 4.0+ AssetsLibrary framework

有比UIImageWriteToSavedPhotosAlbum更快的方法,使用iOS 4.0+ AssetsLibrary框架

    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];

#3


26  

The simplest way is:

最简单的方法是:

UIImageWriteToSavedPhotosAlbum(myUIImage, nil, nil, nil);

For Swift, you can refer to Saving to the iOS photo library using swift

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

#4


12  

One thing to remember: If you use a callback, make sure that your selector conforms to the following form:

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

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

Otherwise, you'll crash with an error such as the following:

否则,您将崩溃的错误如下:

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

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

#5


10  

Just pass the images from an array to it like so

将图像从数组传递给它

-(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);
        }
}

Sorry for typo's kinda just did this on the fly but you get the point

抱歉,打印错误,只是在飞行中做了,但你明白了。

#6


4  

When saving an array of photos, don't use a for loop, do the following

保存照片数组时,不要使用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);
   }
}

#7


4  

In 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.
            }
    }

#8


4  

Below function would work. You can copy from here and paste there...

下面的函数是可行的。你可以从这里复制粘贴。

-(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");
        }
    }];
}

#9


2  

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];
}

#10


1  

my last answer will do it..

我的最后一个答案是……

for each image you want to save, add it to a NSMutableArray

对于要保存的每个图像,将其添加到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);
        }
}

#11


1  

I created a UIImageView category for this, based on some of the answers above.

基于上面的一些答案,我创建了一个UIImageView类别。

Header File:

头文件:

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

Implementation

实现

@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

Now simply call this function on your imageview:

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

[self.imageView addHoldToSave];

Optionally you can alter the minimumPressDuration parameter.

可选地,您可以更改minimumPressDuration参数。

#12


1  

In Swift 2.2

在斯威夫特2.2

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

If you do not want to be notified when the image is done saving then you may pass nil in the completionTarget, completionSelector and contextInfo parameters.

如果您不希望在图像完成保存时被通知,那么您可以在completionTarget、completionSelector和contextInfo参数中传递nil。

Example:

例子:

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.
        }
    }

The important thing to note here is that your method that observes the image saving should have these 3 parameters else you will run into NSInvocation errors.

这里需要注意的重要一点是,观察图像保存的方法应该有这3个参数,否则会遇到nsinvocerror。

Hope it helps.

希望它可以帮助。

#13


0  

You can use this

你可以使用这个

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   UIImageWriteToSavedPhotosAlbum(img.image, nil, nil, nil);
});

#1


395  

You can use this function:

你可以使用这个功能:

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

You only need completionTarget, completionSelector and contextInfo if you want to be notified when the UIImage is done saving, otherwise you can pass in nil.

如果你想在UIImage完成保存时得到通知,你只需要completionTarget, completionSelector和contextInfo,否则你可以传入nil。

See the official documentation for UIImageWriteToSavedPhotosAlbum().

参见UIImageWriteToSavedPhotosAlbum()的官方文档。

#2


63  

Deprecated in iOS 9.0.

在iOS 9.0中弃用。

There`s much more fast then UIImageWriteToSavedPhotosAlbum way to do it using iOS 4.0+ AssetsLibrary framework

有比UIImageWriteToSavedPhotosAlbum更快的方法,使用iOS 4.0+ AssetsLibrary框架

    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];

#3


26  

The simplest way is:

最简单的方法是:

UIImageWriteToSavedPhotosAlbum(myUIImage, nil, nil, nil);

For Swift, you can refer to Saving to the iOS photo library using swift

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

#4


12  

One thing to remember: If you use a callback, make sure that your selector conforms to the following form:

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

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

Otherwise, you'll crash with an error such as the following:

否则,您将崩溃的错误如下:

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

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

#5


10  

Just pass the images from an array to it like so

将图像从数组传递给它

-(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);
        }
}

Sorry for typo's kinda just did this on the fly but you get the point

抱歉,打印错误,只是在飞行中做了,但你明白了。

#6


4  

When saving an array of photos, don't use a for loop, do the following

保存照片数组时,不要使用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);
   }
}

#7


4  

In 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.
            }
    }

#8


4  

Below function would work. You can copy from here and paste there...

下面的函数是可行的。你可以从这里复制粘贴。

-(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");
        }
    }];
}

#9


2  

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];
}

#10


1  

my last answer will do it..

我的最后一个答案是……

for each image you want to save, add it to a NSMutableArray

对于要保存的每个图像,将其添加到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);
        }
}

#11


1  

I created a UIImageView category for this, based on some of the answers above.

基于上面的一些答案,我创建了一个UIImageView类别。

Header File:

头文件:

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

Implementation

实现

@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

Now simply call this function on your imageview:

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

[self.imageView addHoldToSave];

Optionally you can alter the minimumPressDuration parameter.

可选地,您可以更改minimumPressDuration参数。

#12


1  

In Swift 2.2

在斯威夫特2.2

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

If you do not want to be notified when the image is done saving then you may pass nil in the completionTarget, completionSelector and contextInfo parameters.

如果您不希望在图像完成保存时被通知,那么您可以在completionTarget、completionSelector和contextInfo参数中传递nil。

Example:

例子:

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.
        }
    }

The important thing to note here is that your method that observes the image saving should have these 3 parameters else you will run into NSInvocation errors.

这里需要注意的重要一点是,观察图像保存的方法应该有这3个参数,否则会遇到nsinvocerror。

Hope it helps.

希望它可以帮助。

#13


0  

You can use this

你可以使用这个

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   UIImageWriteToSavedPhotosAlbum(img.image, nil, nil, nil);
});