2008-10-07 13 views
182

Que dois-je faire pour sauvegarder une image générée par mon programme (éventuellement à partir de l'appareil photo, peut-être pas) dans la photothèque du système sur l'iPhone?Comment enregistrer une photo dans une photothèque iPhone?

+0

Vous pouvez vérifier [ce code] (http://stackoverflow.com/a/41797659/7030209). Belle journée! –

Répondre

392

Vous pouvez utiliser cette fonction:

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

Vous avez seulement besoin completionTarget, completionSelector et contextInfo si vous souhaitez être averti lorsque le UIImage enregistrement effectué, sinon vous pouvez passer nil . Voir le official documentation for UIImageWriteToSavedPhotosAlbum().

+0

Est-ce que cela fonctionne sur le simulateur? – singingAtom

+6

oui, il fonctionne sur le simulateur – pws5068

+167

Mère de fonctions courtes ..... – Eugene

10

Il suffit de passer les images d'un tableau à elle comme si

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

Désolé pour ne faute de frappe est un peu juste ce à la volée, mais vous obtenez le point

+0

L'utilisation de certaines des photos me manquera, je l'ai essayée. La manière correcte de l'utiliser est d'utiliser le rappel depuis le sélecteur d'achèvement. – SamChen

+1

pouvons-nous enregistrer des images avec le nom personnalisé? –

+0

On ne devrait jamais utiliser de boucle pour cela. Cela conduit à l'état de la course et aux accidents. – saurabh

1

ma dernière réponse le fera ..

pour chaque image que vous souhaitez enregistrer, l'ajouter à un 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); 
     } 
} 
+0

J'ai essayé votre solution, il manquait toujours certaines photos. Jetez un oeil à ma réponse. [link] (http://stackoverflow.com/a/18220664/927208) – SamChen

64

Déconseillé dans iOS 9.0.

beaucoup plus rapide s `puis UIImageWriteToSavedPhotosAlbum façon de le faire en utilisant le framework iOS 4.0+ AssetsLibrary

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

Existe-t-il un moyen d'enregistrer des métadonnées arbitraires avec la photo? – zakdances

+2

J'ai essayé d'enregistrer en utilisant 'ALAssetsLibrary', il faut juste le même temps pour enregistrer en tant que' UIImageWriteToSavedPhotosAlbum'. – Hlung

+0

Et cela gèle la caméra :(Je suppose que ce n'est pas supporté en arrière-plan – Hlung

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

Une chose à retenir: Si vous utilisez un rappel, assurez-vous que votre sélecteur est conforme sous la forme suivante:

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

Sinon, vous écrasez avec une erreur comme celle-ci:

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

4

Lorsque vous enregistrez un tableau de photos, ne pas utiliser une boucle, procédez comme suit

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

Vous pouvez utiliser cette

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

En 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. 
      } 
    } 
+0

oui ... gentil..mais après enregistrer l'image je veux charger l'image de la galerie ... comment faire –

1

J'ai créé une catégorie UIImageView pour cela, basé sur quelques-unes des réponses ci-dessus.

tête de fichier:

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

mise en œuvre

@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 

Maintenant, il suffit d'appeler cette fonction sur votre imageview:

[self.imageView addHoldToSave]; 

option, vous pouvez modifier le paramètre minimumPressDuration.

4

La fonction ci-dessous fonctionnerait. Vous pouvez copier-coller à partir d'ici et là ...

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

En Swift 2,2

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

Si vous ne voulez pas être averti lorsque l'image enregistrement effectué, vous pouvez passer nil dans le achèvementTarget, completionSelector et contextInfo paramètres.

Exemple:

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

La chose importante à noter ici est que votre méthode qui observe l'économie d'image doit avoir ces 3 paramètres sinon vous rencontrez des erreurs NSInvocation.

Espérons que ça aide.