Làm cách nào để lưu ảnh vào thư viện ảnh iPhone?


193

Tôi cần làm gì để lưu hình ảnh mà chương trình của tôi đã tạo (có thể từ máy ảnh, có thể không) vào thư viện ảnh hệ thống trên iPhone?


Bạn có thể kiểm tra mã này . Ngày tuyệt vời!
Celil Bozkurt

Câu trả lời:


411

Bạn có thể sử dụng chức năng này:

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

Bạn chỉ cần completionTarget , completionSelectorcontextinfo nếu bạn muốn được thông báo khi UIImageđược thực hiện tiết kiệm, nếu không bạn có thể vượt qua trong nil.

Xem tài liệu chính thức choUIImageWriteToSavedPhotosAlbum() .


Lấy +1 cho câu trả lời chính xác
Niru Mukund Shah

Hi cảm ơn cho giải pháp tuyệt vời của bạn. Ở đây tôi có một nghi ngờ làm thế nào chúng ta có thể tránh trùng lặp trong khi lưu hình ảnh trong thư viện ảnh. Cảm ơn trước.
Naresh

Nếu bạn muốn tiết kiệm với chất lượng tốt hơn, hãy xem điều này: stackoverflow.com/questions/1379274/iêu
Eonil

4
Bây giờ bạn sẽ cần thêm 'Quyền riêng tư - Mô tả sử dụng bổ sung thư viện ảnh kể từ iOS 11 để lưu ảnh vào album của người dùng.
cưỡi ngựa

1
Làm thế nào để đặt tên cho hình ảnh được lưu?
Giải thưởng

63

Không dùng nữa trong iOS 9.0.

Có cách nhanh hơn UIImageWriteToSattedPhotosAlbum để thực hiện bằng cách sử dụng khung công tác iOS 4.0+ AssetsL Library

    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
Có cách nào để lưu siêu dữ liệu tùy ý cùng với ảnh không?
zakdances

2
Tôi đã cố gắng tiết kiệm bằng cách sử dụng ALAssetsLibrary, nó chỉ mất cùng thời gian để tiết kiệm như UIImageWriteToSavedPhotosAlbum.
Hlung

Và điều này đóng băng máy ảnh :( Tôi đoán nó không được hỗ trợ nền?
Hlung

Cái này sạch hơn rất nhiều b / c bạn có thể sử dụng một khối để xử lý hoàn thành.
jpswain

5
Tôi đang sử dụng mã này và tôi đang bao gồm khung này #import <AssetsL Library / AssetsL Library.h> không phải là AVFoundation. Không nên chỉnh sửa câu trả lời? @Denis
Julian Osorio


13

Một điều cần nhớ: Nếu bạn sử dụng một cuộc gọi lại, hãy đảm bảo rằng bộ chọn của bạn tuân theo mẫu sau:

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

Nếu không, bạn sẽ gặp sự cố với một lỗi như sau:

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


10

Chỉ cần truyền hình ảnh từ một mảng đến nó như vậy

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

Xin lỗi vì typo vừa mới làm điều này một cách nhanh chóng nhưng bạn đã nhận được điểm


Sử dụng điều này sẽ bỏ lỡ một số hình ảnh, tôi đã thử nó. Cách chính xác để sử dụng là sử dụng gọi lại từ bộ chọn hoàn thành.
SamChen

1
chúng ta có thể lưu hình ảnh với tên tùy chỉnh?
Người dùng 1531343

Không bao giờ nên sử dụng cho vòng lặp cho điều này. Nó dẫn đến tình trạng cuộc đua và tai nạn.
saurabh

4

Khi lưu một mảng ảnh, không sử dụng vòng lặp for, hãy làm như sau

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

4

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

vâng ... tốt đẹp..nhưng sau khi lưu hình ảnh tôi muốn tải hình ảnh từ thư viện ... làm thế nào để làm điều đó
EI Captain v2.0

4

Dưới đây chức năng sẽ làm việc. Bạn có thể sao chép từ đây và dán vào đó ...

-(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

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

câu trả lời cuối cùng của tôi sẽ làm điều đó ..

đối với mỗi hình ảnh bạn muốn lưu, hãy thêm nó vào 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);
        }
}

Tôi đã thử giải pháp của bạn, nó luôn bỏ lỡ một số hình ảnh. Hãy nhìn vào câu trả lời của tôi. liên kết
SamChen

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

Câu trả lời này không đúng vì nó không lưu hình ảnh vào Thư viện ảnh hệ thống, mà vào hộp cát.
Evan

1

Tôi đã tạo một thể loại UIImageView cho điều này, dựa trên một số câu trả lời ở trên.

Tập tin tiêu đề:

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

Thực hiện

@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

Bây giờ chỉ cần gọi chức năng này trên hình ảnh của bạn:

[self.imageView addHoldToSave];

Tùy chọn bạn có thể thay đổi tham số minimPressDuration.


1

Trong Swift 2.2

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

Nếu bạn không muốn nhận thông báo khi hình ảnh được thực hiện tiết kiệm thì bạn có thể vượt qua con số không trong completionTarget , completionSelectorcontextinfo tham số.

Thí dụ:

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

Điều quan trọng cần lưu ý ở đây là phương pháp của bạn quan sát việc lưu hình ảnh nên có 3 tham số khác, bạn sẽ gặp phải lỗi NSInvocation.

Hy vọng nó giúp.


0

Bạn có thể sử dụng cái này

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   UIImageWriteToSavedPhotosAlbum(img.image, nil, nil, nil);
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.