Как сохранить картинку в фото-библиотеку iPhone?

Что мне нужно сделать, чтобы сохранить изображение, созданное моей программой (возможно, с камеры, а возможно, нет) в системную библиотеку фотографий на iPhone?

Вы можете проверить этот код. Отличный день!

Celil Bozkurt 23.01.2017 03:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
200
1
160 841
15
Перейти к ответу Данный вопрос помечен как решенный

Ответы 15

Ответ принят как подходящий

Вы можете использовать эту функцию:

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

Вам нужны только CompleteTarget, ЗавершениеСелектор и contextInfo, если вы хотите получать уведомление, когда UIImage завершит сохранение, в противном случае вы можете передать nil.

См. официальная документация для UIImageWriteToSavedPhotosAlbum().

Возьмите +1 за точный ответ

Niru Mukund Shah 19.07.2013 15:43

Привет, спасибо за отличное решение. Здесь у меня есть одно сомнение, как можно избежать дублирования при сохранении изображения в библиотеке фотографий. Заранее спасибо.

Naresh 17.02.2014 19:49

Если хотите сохранить в лучшем качестве, смотрите это: stackoverflow.com/questions/1379274/…

eonil 26.12.2015 10:03

Не забудьте добавить ключ "Конфиденциальность - описание использования библиотеки фотографий" в файл info.plist.

Leo 31.03.2017 01:56

Теперь вам нужно будет добавить «Конфиденциальность - описание использования дополнений фото-библиотеки» в iOS 11, чтобы сохранять фотографии в альбоме пользователей.

horsejockey 01.11.2017 18:26

как дать имя сохраненным изображениям?

Priyal 19.03.2018 10:16

Просто передайте ему изображения из массива вот так

-(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 14.08.2013 02:37

можем ли мы сохранять изображения с произвольным именем?

User 1531343 17.01.2014 10:37

Для этого никогда не следует использовать цикл for. Это приводит к состоянию гонки и сбоям.

saurabh 16.10.2015 10:23

мой последний ответ сделает это ..

для каждого изображения, которое вы хотите сохранить, добавьте его в 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 14.08.2013 03:04

Не рекомендуется в iOS 9.0.

Есть гораздо более быстрый способ сделать это, чем UIImageWriteToSavedPhotosAlbum, с использованием фреймворка AssetsLibrary iOS 4.0+.

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

Есть ли способ сохранить произвольные метаданные вместе с фотографией?

zakdances 17.04.2012 05:12

Я пробовал сохранять с помощью ALAssetsLibrary, на сохранение требуется столько же времени, что и с UIImageWriteToSavedPhotosAlbum.

Hlung 05.05.2012 14:57

И это замораживает камеру :( Я думаю, это не поддерживается в фоновом режиме?

Hlung 05.05.2012 15:27

Этот настолько чище b / c, что вы можете использовать блок для обработки завершения.

jpswain 30.09.2013 08:33

Я использую этот код и включаю этот фреймворк #import <AssetsLibrary / AssetsLibrary.h>, а не AVFoundation. Разве ответ нельзя отредактировать? @Денис

Julian Osorio 24.04.2014 00:47

Красиво, но не рекомендуется в iOS 9 SDK.

eonil 26.12.2015 09:53

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

Этот ответ неверен, потому что он сохраняет изображение не в системной библиотеке фотографий, а в песочнице.

Evan 05.04.2020 08:34

Следует помнить одну вещь: если вы используете обратный вызов, убедитесь, что ваш селектор соответствует следующей форме:

- (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 вы можете обратиться к Сохранение в фото-библиотеку iOS с помощью swift

Мне очень нравится ваш значок профиля пользователя SO. Довольно крутое изображение Xcode.

Supertecnoboff 29.05.2015 12:32

Фантастически просто и очень-очень просто!

Septronic 07.09.2015 04:15

Вы можете использовать это

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

да ... красиво ... но после сохранения изображения я хочу загрузить изображение из галереи ... как это сделать

EI Captain v2.0 25.07.2015 13:36

Я создал для этого категорию 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.

Ниже будет работать функция. Вы можете скопировать отсюда и вставить туда ...

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

В Swift 2.2

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

Если вы не хотите получать уведомления о завершении сохранения изображения, вы можете указать nil в параметрах CompleteTarget, ЗавершениеСелектор и contextInfo.

Пример:

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.

Надеюсь, это поможет.

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!")
    }
}

Для Swift 5.0

Я использовал этот код для копирования изображений в фотоальбомы, созданные моим приложением; Когда я хочу скопировать файлы изображений, я вызываю функцию startSavingPhotoAlbume (). Сначала я получаю UIImage из папки приложения, а затем сохраняю его в фотоальбомах. Поскольку это не имеет значения, я не показываю, как читать изображение из папки приложения.

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

Другие вопросы по теме