아이폰 사진 보관함에 사진을 저장하는 방법?


193

내 프로그램에서 생성 한 이미지를 카메라에서 (아마도 아닐 수도 있음) iPhone의 시스템 사진 라이브러리에 저장하려면 어떻게해야합니까?


이 코드 를 확인할 수 있습니다 . 좋은 하루!
Celil Bozkurt

답변:


411

이 기능을 사용할 수 있습니다 :

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

저장이 완료 되면 알림을 받으려면 completionTarget , completionSelectorcontextInfo 만 필요합니다 . UIImage그렇지 않으면을 전달할 수 있습니다 nil.

에 대한 공식 문서를UIImageWriteToSavedPhotosAlbum() 참조하십시오 .


정확한 답변을 얻으려면 +1을하세요
Niru Mukund Shah

훌륭한 솔루션에 감사드립니다. 여기서 사진 라이브러리에 이미지를 저장하는 동안 중복을 피할 수있는 방법에 의구심이 있습니다. 미리 감사드립니다.
Naresh

더 나은 품질로 저장하려면 다음을 참조하십시오 : stackoverflow.com/questions/1379274/…
eonil

4
이제 사용자 앨범 사진을 저장하려면 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

2
을 사용하여 저장을 시도했지만으로 저장 ALAssetsLibrary하는 데 동일한 시간이 걸립니다 UIImageWriteToSavedPhotosAlbum.
Hlung

그리고 이것은 카메라를 정지시킵니다 : (배경이 지원되지 않는 것 같아요?
Hlung

이것은 블록을 사용하여 완료를 처리 할 수있는 훨씬 깨끗한 b / c입니다.
jpswain

5
이 코드를 사용하고 있으며 AVFoundation이 아닌이 프레임 워크 #import <AssetsLibrary / AssetsLibrary.h>를 포함하고 있습니다. 답변을 편집해서는 안됩니까? @Denis
Julian Osorio


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
맞춤 이름으로 이미지를 저장할 수 있습니까?
사용자 1531343

이것을 위해 for 루프를 사용해서는 안됩니다. 경쟁 조건으로 이어지고 충돌합니다.
saurabh

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

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

이미지 저장 난 갤러리에서 이미지를로드하려는 후 네 ... nice..but ... 어떻게해야 할 일
EI 캡틴 2.0

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

2

스위프트 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

내 마지막 답변은 ..

저장하려는 각 이미지에 대해 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);
        }
}

귀하의 솔루션을 시도했지만 항상 사진 중 일부를 놓쳤습니다. 내 대답을 봐 링크
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];
}

이 대답은 이미지를 시스템 사진 라이브러리가 아니라 샌드 박스에 저장하기 때문에 옳지 않습니다.
에반

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

이제 이미지 뷰에서이 함수를 호출하면됩니다.

[self.imageView addHoldToSave];

선택적으로 minimumPressDuration 매개 변수를 변경할 수 있습니다.


1

에서 스위프트 2.2

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

이미지 저장이 완료 될 때 알림을받지 않으려면 completionTarget , completionSelectorcontextInfo 매개 변수에 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 오류가 발생한다는 것입니다.

도움이 되길 바랍니다.


0

이것을 사용할 수 있습니다

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   UIImageWriteToSavedPhotosAlbum(img.image, nil, nil, nil);
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.