Wie speichere ich ein Bild in der iPhone-Fotobibliothek?

193

Was muss ich tun, um ein von meinem Programm erzeugtes Bild (möglicherweise von der Kamera, möglicherweise nicht) in der Systemfotobibliothek auf dem iPhone zu speichern?

jblocksom
quelle
Sie können diesen Code überprüfen . Schöner Tag!
Celil Bozkurt

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

Martin Gordon
quelle
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];
Denis Fileev
quelle
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
30

Der einfachste Weg ist:

UIImageWriteToSavedPhotosAlbum(myUIImage, nil, nil, nil);

Weitere SwiftInformationen finden Sie unter Speichern in der iOS-Fotobibliothek mit Swift

Mutawe
quelle
3
Ihr SO-Benutzerprofilsymbol gefällt mir sehr gut. Ziemlich cooles Xcode-Bild.
Supertecnoboff
1
Fantastisch einfach und sehr sehr einfach!
Septronic
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]

Jeff C.
quelle
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

mrburns05
quelle
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);
   }
}
SamChen
quelle
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.
            }
    }
König-Zauberer
quelle
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");
        }
    }];
}
iDevAmit
quelle
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!")
    }
}
luhuiya
quelle
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);
        }
}
mrburns05
quelle
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];
}
Hallo
quelle
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.

HugglesNL
quelle
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.

Jarora
quelle
0

Sie können dies verwenden

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