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

114

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

J'ai récupéré et placé l'image dans 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 n'ai aucune idée de comment l'enregistrer. J'enregistre tous les autres éléments de la vue (principalement UITextfield) dans Core Data. J'ai recherché et recherché et essayé de nombreux morceaux de code suggérés par les gens, mais soit je ne saisis pas correctement le code, soit ces suggestions ne fonctionnent pas avec la configuration de mon code. C'est probablement le premier. Je voudrais enregistrer l'image dans UIImageView en utilisant la même action (un bouton d'enregistrement) que j'utilise pour enregistrer le texte dans UITextFields. Voici comment j'enregistre 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 ne peux pas le comprendre. Pour la première fois de ma vie, j'ai voulu causer des dommages physiques à un objet inanimé, mais j'ai réussi à me retenir.

Je voudrais 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 une autre UIImageView pour l'afficher lorsque l'utilisateur pousse cette vue sur la pile. Toute aide est grandement appréciée!

oublié
la source

Réponses:

341

Tout va bien, mec. Ne vous faites pas de mal ni aux autres.

Vous ne souhaitez probablement pas stocker ces images dans Core Data, car cela peut avoir un impact sur les performances si l'ensemble de données devient 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 jonché 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.

Danilo Campos
la source
2
tout à fait correct - je veux juste mentionner les directives de stockage Apple, donc EN FONCTION de la nature des images, elles doivent être stockées sous Caches
Daij-Djan
J'ai suivi votre suggestion et votre code. mais il n'apparaît pas dans les sections photos. Comment est-ce arrivé?
NovusMobile
@DaniloCampos Comment créer un dossier dans le répertoire de documents puis enregistrer le fichier dans ce dossier?
Pradeep Reddy Kypa
3

Version Swift 3.0

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)
}
Fangming
la source
2

C'est la réponse de Fangming Ning pour Swift 4.2 , mise à jour avec une méthode Swifty recommandée et plus 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 également.

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.

Tamás Sengel
la source
Est-ce correct? Au cours d'une réponse à une autre question ici , je trouve que fileURLWithPathainsi absoluteStringest faux.
dumbledad
@dumbledad Merci pour l'information, j'ai mis à jour ma réponse et réécrit le code pour Swift 4.2 également.
Tamás Sengel
2
#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 - 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;
}
Mannam Brahmam
la source
1

Swift 4 avec extension

extension UIImage{

func saveImage(inDir:FileManager.SearchPathDirectory,name:String){
    guard let documentDirectoryPath = FileManager.default.urls(for: inDir, in: .userDomainMask).first else {
        return
    }
    let img = UIImage(named: "\(name).jpg")!

    // Change extension if you want to save as PNG.
    let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("\(name).jpg").absoluteString)
    do {
        try UIImageJPEGRepresentation(img, 0.5)?.write(to: imgPath, options: .atomic)
    } catch {
        print(error.localizedDescription)
    }
  }
}

Exemple d'utilisation

 image.saveImage(inDir: .documentDirectory, name: "pic")
levin varghese
la source
0

Dans Swift:

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