web-dev-qa-db-fra.com

Enregistrer une image dans le dossier Documents d'application à partir d'UIView sur IOS

J'ai un UIImageView qui permet à un utilisateur de placer et de conserver une image jusqu'à ce qu'elle puisse être sauvegardée. Le problème, c'est que je ne vois pas comment sauvegarder et récupérer l'image que j'ai placée dans la vue.

J'ai récupéré et placé l'image dans le UIImageView comme ceci:

//Get Image 
- (void) getPicture:(id)sender {
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = (sender == myPic) ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypeSavedPhotosAlbum;
    [self presentModalViewController:picker animated:YES];
    [picker release];
}


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage (UIImage *)image editingInfo:(NSDictionary *)editingInfo {
    myPic.image = image;
    [picker dismissModalViewControllerAnimated:YES];
}

Il affiche très bien l’image sélectionnée dans mon UIImageView, mais je ne sais pas comment le sauvegarder. J'enregistre toutes les autres parties de la vue (principalement UITextfield) dans Core Data. J'ai cherché et cherché, et essayé beaucoup de morceaux de code suggérés par les gens, mais soit je ne saisis pas le code correctement, soit ces suggestions ne fonctionnent pas avec la configuration de mon code. C'est probablement l'ancien. J'aimerais enregistrer l'image dans UIImageView en utilisant la même action (un bouton Enregistrer) que j'utilise pour enregistrer le texte dans UITextFields. Voici comment je sauvegarde mes informations UITextField:

// Handle Save Button
- (void)save {

    // Get Info From UI
    [self.referringObject setValue:self.myInfo.text forKey:@"myInfo"];

Comme je l’ai dit plus tôt, j’ai essayé plusieurs méthodes pour que cela fonctionne, mais je n’arrive pas à comprendre. Pour la première fois de ma vie, j'ai voulu causer un préjudice physique à un objet inanimé, mais j'ai réussi à me retenir. 

J'aimerais pouvoir enregistrer l'image que l'utilisateur place dans UIImageView dans le dossier de documents de l'application, puis pouvoir la récupérer et la placer dans un autre UIImageView pour l'afficher lorsque l'utilisateur place cette vue dans la pile. Toute aide est grandement appréciée!

105
forgot

C'est tout bon, mec. Ne te fais pas de mal ni à autrui.

Vous ne voulez probablement pas stocker ces images dans Core Data, car cela pourrait avoir un impact sur les performances si le jeu de données devenait trop volumineux. Mieux vaut écrire les images dans des fichiers.

NSData *pngData = UIImagePNGRepresentation(image);

Cela extrait les données PNG de l'image que vous avez capturée. De là, vous pouvez l'écrire dans un fichier:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);  
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory 
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"image.png"]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file

Le lire plus tard fonctionne de la même manière. Construisez le chemin comme nous venons de le faire ci-dessus, puis:

NSData *pngData = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [UIImage imageWithData:pngData];

Ce que vous voudrez probablement faire est de créer une méthode qui crée des chaînes de chemin pour vous, car vous ne voulez pas que ce code soit jeté partout. Cela pourrait ressembler à ceci:

- (NSString *)documentsPathForFileName:(NSString *)name
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);  
    NSString *documentsPath = [paths objectAtIndex:0];

    return [documentsPath stringByAppendingPathComponent:name]; 
}

J'espère que c'est utile.

332
Danilo Campos

Swift 3.0 version

let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString

let img = UIImage(named: "1.jpg")!// Or use whatever way to get the UIImage object
let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("1.jpg"))// Change extension if you want to save as PNG

do{
    try UIImageJPEGRepresentation(img, 1.0)?.write(to: imgPath, options: .atomic)//Use UIImagePNGRepresentation if you want to save as PNG
}catch let error{
    print(error.localizedDescription)
}
3
Fangming
#pragma mark == Save Image To Local Directory

-(void)saveImageToDocumentDirectoryWithImage: (UIImage *)capturedImage {
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:@"/images"];

//Create a folder inside Document Directory
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
    [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder

NSString *imageName = [NSString stringWithFormat:@"%@/img_%@.png", dataPath, [self getRandomNumber]] ;
// save the file
if ([[NSFileManager defaultManager] fileExistsAtPath:imageName]) {
    // delete if exist
    [[NSFileManager defaultManager] removeItemAtPath:imageName error:nil];
}

NSData *imageDate = [NSData dataWithData:UIImagePNGRepresentation(capturedImage)];
[imageDate writeToFile: imageName atomically: YES];
}

#pragma mark
#pragma mark == Generate Random Number
-(NSString *)getRandomNumber{
NSTimeInterval time = ([[NSDate date] timeIntervalSince1970]); // returned as a double
long digits = (long)time; // this is the first 10 digits
int decimalDigits = (int)(fmod(time, 1) * 1000); // this will get the 3 missing digits
//long timestamp = (digits * 1000) + decimalDigits;
NSString *timestampString = [NSString stringWithFormat:@"%ld%d",digits ,decimalDigits];
return timestampString;
}
0
Mannam Brahmam

Ceci est la réponse de Fangming Ningpour Swift 4.2, mise à jour avec une méthode recommandée et plus de Swifty pour récupérer le chemin du répertoire du document et avec une meilleure documentation. Crédits à Fangming Ning pour la nouvelle méthode aussi.

guard let documentDirectoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
    return
}

//Using force unwrapping here because we're sure "1.jpg" exists. Remember, this is just an example.
let img = UIImage(named: "1.jpg")!

// Change extension if you want to save as PNG.
let imgPath = documentDirectoryPath.appendingPathComponent("1.jpg")

do {
    //Use .pngData() if you want to save as PNG.
    //.atomic is just an example here, check out other writing options as well. (see the link under this example)
    //(atomic writes data to a temporary file first and sending that file to its final destination)
    try img.jpegData(compressionQuality: 1)?.write(to: imgPath, options: .atomic)
} catch {
    print(error.localizedDescription)
}

Découvrez toutes les options d'écriture de données possibles ici.

0
Tamás Sengel

En rapide: 

let paths: [NSString?] = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .LocalDomainMask, true)
if let path = paths[0]?.stringByAppendingPathComponent(imageName) {
    do {
        try UIImagePNGRepresentation(image)?.writeToFile(path, options: .DataWritingAtomic)
    } catch {
        return
    }
}
0
NatashaTheRobot