Guarde una imagen en la carpeta de documentos de la aplicación desde UIView en IOS


114

Tengo un UIImageView que permite a un usuario colocar y mantener una imagen hasta que se pueda guardar. El problema es que no puedo averiguar cómo guardar y recuperar la imagen que he colocado en la vista.

He recuperado y colocado la imagen en UIImageView así:

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

Muestra la imagen seleccionada en mi UIImageView muy bien, pero no tengo idea de cómo guardarla. Estoy guardando todas las demás partes de la vista (principalmente UITextfield) en Core Data. He buscado y buscado y he probado muchos fragmentos de código que la gente ha sugerido, pero no estoy ingresando el código correctamente o esas sugerencias no funcionan con la forma en que configuré mi código. Probablemente sea lo primero. Me gustaría guardar la imagen en UIImageView usando la misma acción (un botón de guardar) que estoy usando para guardar el texto en UITextFields. Así es como guardo mi información de UITextField:

// Handle Save Button
- (void)save {

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

Como dije antes, he probado varios métodos para que esto funcione, pero no puedo entenderlo. Por primera vez en mi vida he querido causar daño físico a un objeto inanimado, pero he logrado contenerme.

Me gustaría poder guardar la imagen que el usuario coloca en UIImageView en la carpeta de documentos de la aplicación, y luego poder recuperarla y colocarla en otro UIImageView para mostrarla cuando el usuario empuja esa vista en la pila. ¡Cualquier ayuda es muy apreciada!

Respuestas:


341

Todo está bien, hombre. No te hagas daño a ti mismo ni a los demás.

Probablemente no desee almacenar estas imágenes en Core Data, ya que eso puede afectar el rendimiento si el conjunto de datos crece demasiado. Es mejor escribir las imágenes en archivos.

NSData *pngData = UIImagePNGRepresentation(image);

Esto extrae datos PNG de la imagen que ha capturado. Desde aquí, puede escribirlo en un archivo:

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

Leerlo más tarde funciona de la misma manera. Construya la ruta como acabamos de hacer arriba, luego:

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

Lo que probablemente querrá hacer es crear un método que cree cadenas de ruta para usted, ya que no quiere que ese código se ensucie por todas partes. Podría verse así:

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

    return [documentsPath stringByAppendingPathComponent:name]; 
}

Espero que sea de ayuda.


2
Totalmente correcto, solo quiero mencionar las Pautas de almacenamiento de Apple, por lo que DEPENDIENDO de la naturaleza de las imágenes, debe almacenarse en Caches
Daij-Djan

Seguí tu sugerencia y código. pero no aparece en las secciones de fotos. ¿Cómo pasó esto?
NovusMobile

@DaniloCampos ¿Cómo crear una carpeta dentro del directorio de documentos y luego guardar el archivo dentro de esa carpeta?
Pradeep Reddy Kypa

3

Versión 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)
}

2

Esta es la respuesta de Fangming Ning para Swift 4.2 , actualizada con un método recomendado y más rápido para recuperar la ruta del directorio de documentos y con mejor documentación. Créditos a Fangming Ning por el nuevo método también.

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

Consulte todas las opciones de escritura de datos posibles aquí.


¿Es esto correcto? En una respuesta a otra pregunta aquí , encontré que fileURLWithPathjunto con absoluteStringestá mal.
dumbledad

@dumbledad Gracias por la información, actualicé mi respuesta y también reescribí el código para Swift 4.2.
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;
}

1

Swift 4 con extensión

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

Ejemplo de uso

 image.saveImage(inDir: .documentDirectory, name: "pic")

0

En 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
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.