Wie speichere ich ein Bild in der iPhone-Fotobibliothek?


Antworten:


411

Sie können diese Funktion verwenden:

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

Sie benötigen Nur CompletionTarget , CompletionSelector und ContextInfo, wenn Sie benachrichtigt werden möchten, wenn das UIImageSpeichern abgeschlossen ist. Andernfalls können Sie übergeben nil.

Siehe die offizielle Dokumentation fürUIImageWriteToSavedPhotosAlbum() .


Nehmen Sie +1 für die genaue Antwort
Niru Mukund Shah

Hallo, danke für deine großartige Lösung. Hier habe ich einen Zweifel, wie wir Duplikate beim Speichern von Bildern in der Fotobibliothek vermeiden können. Danke im Voraus.
Naresh

Wenn Sie in besserer Qualität speichern möchten, sehen Sie dies: stackoverflow.com/questions/1379274/…
Eonil

4
Sie müssen jetzt ab iOS 11 "Datenschutz - Beschreibung der Verwendung von Fotobibliotheken" hinzufügen, um Fotos im Album des Benutzers zu speichern.
Horsejockey

1
Wie kann man den gespeicherten Bildern einen Namen geben?
Priyal

63

In iOS 9.0 veraltet.

Es gibt viel schneller als UIImageWriteToSavedPhotosAlbum, dies mit dem iOS 4.0+ AssetsLibrary-Framework zu tun

    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
Gibt es eine Möglichkeit, beliebige Metadaten zusammen mit dem Foto zu speichern?
Zakdances

2
Ich habe versucht, mit ALAssetsLibraryzu speichern UIImageWriteToSavedPhotosAlbum. Das Speichern dauert genauso lange wie .
Hlung

Und das friert die Kamera ein :( Ich denke, es wird kein Hintergrund unterstützt?
Hlung

Dieser ist so viel sauberer, dass Sie einen Block verwenden können, um die Fertigstellung zu handhaben.
Jpswain

5
Ich verwende diesen Code und füge dieses Framework #import <AssetsLibrary / AssetsLibrary.h> hinzu, nicht die AVFoundation. Sollte die Antwort nicht bearbeitet werden? @ Denis
Julian Osorio


13

Beachten Sie Folgendes: Wenn Sie einen Rückruf verwenden, stellen Sie sicher, dass Ihr Selektor dem folgenden Formular entspricht:

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

Andernfalls stürzen Sie mit einem Fehler wie dem folgenden ab:

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


10

Übergeben Sie einfach die Bilder von einem Array wie folgt

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

Tut mir leid, dass Tippfehler dies im laufenden Betrieb getan haben, aber Sie verstehen es


Wenn Sie dies verwenden, werden einige der Fotos fehlen, ich habe es versucht. Der richtige Weg dorthin ist die Verwendung des Rückrufs von der Abschlussauswahl.
SamChen

1
Können wir Bilder mit dem benutzerdefinierten Namen speichern?
Benutzer 1531343

Man sollte dafür niemals eine for-Schleife verwenden. Es führt zum Rennzustand und stürzt ab.
Saurabh

4

Verwenden Sie beim Speichern eines Arrays von Fotos keine for-Schleife. Gehen Sie wie folgt vor

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

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

ja ... schön ... aber nach dem Speichern des Bildes möchte ich das Bild aus der Galerie laden ... wie das geht
EI Captain v2.0

4

Die folgende Funktion würde funktionieren. Sie können von hier kopieren und dort einfügen ...

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

meine letzte Antwort wird es tun ..

Fügen Sie jedes Bild, das Sie speichern möchten, einem NSMutableArray hinzu

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

Ich habe Ihre Lösung ausprobiert, es wurden immer einige Fotos übersehen. Schau dir meine Antwort an. Link
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];
}

Diese Antwort ist nicht richtig, da das Bild nicht in der Systemfotobibliothek, sondern in der Sandbox gespeichert wird.
Evan

1

Ich habe hierfür eine UIImageView-Kategorie erstellt, basierend auf einigen der obigen Antworten.

Header-Datei:

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

Implementierung

@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

Rufen Sie jetzt einfach diese Funktion in Ihrer Bildansicht auf:

[self.imageView addHoldToSave];

Optional können Sie den Parameter MinimumPressDuration ändern.


1

In Swift 2.2

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

Wenn Sie nicht benachrichtigt werden möchten, wenn das Speichern des Bildes abgeschlossen ist, können Sie in den Parametern CompletionTarget , CompletionSelector und contextInfo Null übergeben .

Beispiel:

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

Das Wichtigste dabei ist, dass Ihre Methode, die das Speichern von Bildern beobachtet, diese drei Parameter haben sollte. Andernfalls treten NSInvocation-Fehler auf.

Ich hoffe es hilft.


0

Sie können dies verwenden

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   UIImageWriteToSavedPhotosAlbum(img.image, nil, nil, nil);
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.