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

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

165014 次浏览

你可以使用这个函数:

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

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

参见UIImageWriteToSavedPhotosAlbum()的官方文档

就像这样把图像从数组传递给它

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

很抱歉我写错了,不过你懂的

我最后一个答案就行了。

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

在iOS 9.0中已弃用。

有比UIImageWriteToSavedPhotosAlbum更快的方法来使用iOS 4.0+ assetlibrary框架

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

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

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

否则,你会崩溃,出现如下错误:

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

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

最简单的方法是:

UIImageWriteToSavedPhotosAlbum(myUIImage, nil, nil, nil);

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

你可以用这个

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

斯威夫特:

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

我为此创建了一个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参数。

下面的函数可以工作。你可以从这里复制,然后粘贴到那里……

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

斯威夫特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错误。

希望能有所帮助。

斯威夫特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!")
}
}

针对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")
}
}
}