Es posible guardar las imágenes en NSUserDefaults como un objeto y, a continuación, recuperar para su uso posterior?

InformationsquelleAutor Florik | 2011-07-11

12 Comentarios

  1. 81

    ATENCIÓN! SI trabajas en iOS8/XCODE6 VER MIS actualizaciones por DEBAJO de

    Para aquellos que todavía buscan la respuesta es aquí el código de «conveniente» para guardar la imagen en NSUserDefaults. Usted NO DEBE guardar los datos de imagen directamente en NSUserDefaults!

    Escribir datos:

    //Get image data. Here you can use UIImagePNGRepresentation if you need transparency
    NSData *imageData = UIImageJPEGRepresentation(image, 1);
    
    //Get image path in user's folder and store file with name image_CurrentTimestamp.jpg (see documentsPathForFileName below)
    NSString *imagePath = [self documentsPathForFileName:[NSString stringWithFormat:@"image_%f.jpg", [NSDate timeIntervalSinceReferenceDate]]];
    
    //Write image data to user's folder
    [imageData writeToFile:imagePath atomically:YES];
    
    //Store path in NSUserDefaults
    [[NSUserDefaults standardUserDefaults] setObject:imagePath forKey:kPLDefaultsAvatarUrl];
    
    //Sync user defaults
    [[NSUserDefaults standardUserDefaults] synchronize];

    De lectura de datos:

    NSString *imagePath = [[NSUserDefaults standardUserDefaults] objectForKey:kPLDefaultsAvatarUrl];
    if (imagePath) {
        self.avatarImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath]];
    }

    documentsPathForFileName:

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

    Para iOS8/XCODE6
    Como tmr y DevC mencionado en los comentarios de abajo hay un problema con xcode6/ios8. La diferencia entre xcode5 y xcode 6 proceso de instalación es que xcode6 cambios apps UUID después de cada carrera en xcode (ver hightlighted parte en la ruta: /var/mobile/Contenedores/Datos/Aplicación/B0D49CF5-8FBE-4F14-87AE-FA8C16A678B1/Documents/image.jpg).

    Por lo que hay 2 soluciones:

    1. Saltar ese problema, ya que una vez instalada la aplicación en el dispositivo real que nunca cambia UUID (de hecho lo hace, pero es la nueva aplicación)
    2. Guardar ruta relativa a la carpeta correspondiente (en nuestro caso a la aplicación de la raíz)

    Aquí es swift versión de código como un bono (con 2da enfoque):

    Escribir datos:

    let imageData = UIImageJPEGRepresentation(image, 1)
    let relativePath = "image_\(NSDate.timeIntervalSinceReferenceDate()).jpg"
    let path = self.documentsPathForFileName(relativePath)
    imageData.writeToFile(path, atomically: true)
    NSUserDefaults.standardUserDefaults().setObject(relativePath, forKey: "path")
    NSUserDefaults.standardUserDefaults().synchronize()

    De lectura de datos:

    let possibleOldImagePath = NSUserDefaults.standardUserDefaults().objectForKey("path") as String?
    if let oldImagePath = possibleOldImagePath {
        let oldFullPath = self.documentsPathForFileName(oldImagePath)
        let oldImageData = NSData(contentsOfFile: oldFullPath)
        //here is your saved image:
        let oldImage = UIImage(data: oldImageData)
    }

    documentsPathForFileName:

    func documentsPathForFileName(name: String) -> String {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true);
        let path = paths[0] as String;
        let fullPath = path.stringByAppendingPathComponent(name)
    
        return fullPath
    }
    • el código no me funciona la primera vez, no fue capaz de recuperar la imagen de disco. ruta a la carpeta de documentos fue diferente entre la aplicación se ejecuta. podría ser un problema de absoluta frente a las rutas de acceso relativas? el código fue escrito a uno *imagePath, pero en la próxima vez que ejecute la aplicación, se necesita un diferente *imagePath para obtener el archivo. solución simple era para guardar sólo el nombre de archivo en nsuserdefaults, y en la siguiente aplicación se ejecute, volver a obtener los documentos de la carpeta de la ruta, anexar el nombre de archivo, y el resto de código que funcionó muy bien! (gracias Nikita se Llevó)
    • ADVERTENCIA!! Ya No funciona para iOS8
    • Así que, esencialmente, el iOS8/Xcode 6 problema es completamente nula si principalmente se ejecuta en el dispositivo?
    • Solo quiero añadir: el Uso de PNGRepresentation no los va a salvar de Orientación automáticamente los metadatos. Usted tendrá que hacer esto manualmente, o simplemente utilizar la versión JPEG.
    • Va a guardar las imágenes a la ubicación afecta a los datos de iCloud – significado si no es generado por el usuario no debemos salvar a ese lugar?
    • de acuerdo a las recomendaciones de Apple no se debe guardar no-contenido generado por el usuario para directorio de documento. El código de arriba es solo un ejemplo de almacenamiento de imágenes. Si usted guardarlos en el directorio de la caché podría ser eliminado una vez y necesita un código para manejar esa situación
    • Gracias. He creado un nuevo directorio dentro del directorio de documentos y se añade el NSURLIsExcludedFromBackupKey el valor de los recursos (como se explica aquí: developer.apple.com/library/ios/qa/qa1719/_index.html). Yo la necesitaba para estar en el directorio de documentos de porque tiene que ser muy persistentes. ¿Crees que esta bien? O es que hay otro lugar que te recomendamos?
    • ¿Qué acerca de una matriz de imágenes? ¿Cómo puedo hacerlo?
    • Nota: los Nombres de Archivo pueden no ser capaces de superar los 255 caracteres dependiendo del sistema operativo. No es un problema para el script específico que se prestó, pero puede ser un problema para las personas que modificar (como a mí).

  2. 137

    Para guardar una imagen en NSUserDefaults:

    [[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:key];

    Para recuperar una imagen de NSUserDefaults:

    NSData* imageData = [[NSUserDefaults standardUserDefaults] objectForKey:key];
    UIImage* image = [UIImage imageWithData:imageData];
    • Técnicamente correcto, positivamente, que no se recomienda. NSUserDefaults salidas a un plist, que obviamente NO es el lugar para que los datos de imagen raw.
    • He leído que un plist se almacenan en formato binario en estos días en mac osx. Si se utiliza entre una extensión y que contiene la aplicación de la IPC se utiliza (un archivo puede o no puede ser utilizado en el medio). Así que ¿cuál es el problema?
    • Esta pregunta se refiere al iPhone/iPad. Sin embargo, hasta que Apple doc recomendar lo contrario, NSUserDefaults es para los pequeños de preferencias de la aplicación y no de almacenamiento. Como se especifica (developer.apple.com/Library/mac/documentation/Cocoa/Reference/…), «La NSUserDefaults clase proporciona métodos de conveniencia para acceder a los tipos comunes tales como flotadores, dobles, enteros, Booleanos, y las direcciones Url»
    • así que ¿cuál es la forma recomendada de almacenamiento de, digamos, la imagen de perfil para una aplicación donde el usuario se registra? No quiero usar CoreData sólo para almacenar 1 imagen y me siento como golpear el almacenamiento en la nube/db cada vez que lo necesito para mostrar la imagen es caro o no es necesario.
    • sólo tienes que escribir en el sistema de ficheros, y guardar la dirección URL en NSUserDefaults
  3. 26

    Aunque es posible guardar un UIImage a NSUserDefaults, que a menudo no se recomienda, ya que no es la manera más eficiente para guardar las imágenes; una manera más eficiente, es para guardar la imagen en la aplicación del Documents Directory.

    Para el propósito de esta pregunta, he adjuntado la respuesta a su pregunta, junto con la forma más eficiente de ahorrar un UIImage.


    NSUserDefaults (No Recomendado)

    De ahorro para NSUserDefaults

    Este método le permite guardar cualquier UIImage a NSUserDefaults.

    -(void)saveImageToUserDefaults:(UIImage *)image ofType:(NSString *)extension forKey:(NSString *)key {
        NSData * data;
    
        if ([[extension lowercaseString] isEqualToString:@"png"]) {
            data = UIImagePNGRepresentation(image);
        } else if ([[extension lowercaseString] isEqualToString:@"jpg"]) {
            data = UIImageJPEGRepresentation(image, 1.0);
        }
    
        NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
        [userDefaults setObject:data forKey:key];
        [userDefaults synchronize];
    }

    Esta es la forma en que usted lo llame:

    [self saveImageToUserDefaults:image ofType:@"jpg" forKey:@"myImage"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    Carga De NSUserDefaults

    Este método permite cargar cualquier UIImage de NSUserDefaults.

    -(UIImage *)loadImageFromUserDefaultsForKey:(NSString *)key {
        NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
        return [UIImage imageWithData:[userDefaults objectForKey:key]];
    }

    Esta es la forma en que usted lo llame:

    UIImage * image = [self loadImageFromUserDefaultsForKey:@"myImage"];

    Una Mejor Alternativa

    De ahorro para el Directorio de Documentos de

    Este método le permite guardar cualquier UIImage a la Documents Directory dentro de la aplicación.

    -(void)saveImage:(UIImage *)image withFileName:(NSString *)imageName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
        if ([[extension lowercaseString] isEqualToString:@"png"]) {
            [UIImagePNGRepresentation(image) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"png"]] options:NSAtomicWrite error:nil];
        } else if ([[extension lowercaseString] isEqualToString:@"jpg"] || [[extension lowercaseString] isEqualToString:@"jpeg"]) {
            [UIImageJPEGRepresentation(image, 1.0) writeToFile:[directoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageName, @"jpg"]] options:NSAtomicWrite error:nil];
        } else {
            NSLog(@"Image Save Failed\nExtension: (%@) is not recognized, use (PNG/JPG)", extension);
        }
    }

    Esta es la forma en que usted lo llame:

    NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    [self saveImage:image withFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];

    Carga De Directorio De Documentos

    Este método permite cargar cualquier UIImage de la aplicación Documents Directory.

    -(UIImage *)loadImageWithFileName:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
        UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.%@", directoryPath, fileName, [extension lowercaseString]]];
    
        return result;
    }

    Esta es la forma en que usted lo llame:

    NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    UIImage * image = [self loadImageWithFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];

    Una Alternativa Diferente

    Ahorro UIImage a la Biblioteca de Fotos

    Este método le permite guardar cualquier UIImage del dispositivo Photo Library, y se llama de la siguiente manera:

    UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);

    Guardar múltiples UIImages a la Biblioteca de Fotos

    Este método permite guardar múltiples UIImages del dispositivo Photo Library.

    -(void)saveImagesToPhotoAlbums:(NSArray *)images {
        for (int x = 0; x < [images count]; x++) {
            UIImage * image = [images objectAtIndex:x];
    
            if (image != nil) UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
        }
    }

    Esta es la forma en que usted lo llame:

    [self saveImagesToPhotoAlbums:images];

    Donde images es su NSArray compuesto de UIImages.

    • Gran post!!! ¿Cómo saber qué directorio establecido para la entrada inDirectory:(NSString *)directoryPath – podrías llamarlo lo que quieras como «myAppData»??
    • Bueno, en este caso, he utilizado los Documentos de la ruta de acceso del Directorio como argumento. Sin embargo, puede utilizar cualquier directorio que usted tiene acceso a dentro de tu aplicación sandbox/bundle.
  4. 8

    Para swift 2.2

    A la tienda:

    NSUserDefaults.standardUserDefaults().setObject(UIImagePNGRepresentation(chosenImage), forKey: kKeyImage)

    A recuperar:

    if let imageData = NSUserDefaults.standardUserDefaults().objectForKey(kKeyImage),
                let image = UIImage(data: imageData as! NSData){
                //use your image here...
    }
  5. 6

    Para Swift 4

    He intentado casi todo en esta pregunta pero nadie se trabajó para mí. y encontré mi solución.
    primero he creado una extensión para UserDefaults como el de abajo, a continuación, sólo llamados métodos get y set.

    extension UserDefaults {
        func imageForKey(key: String) -> UIImage? {
            var image: UIImage?
            if let imageData = data(forKey: key) {
                image = NSKeyedUnarchiver.unarchiveObject(with: imageData) as? UIImage
            }
            return image
        }
        func setImage(image: UIImage?, forKey key: String) {
            var imageData: NSData?
            if let image = image {
                imageData = NSKeyedArchiver.archivedData(withRootObject: image) as NSData?
            }
            set(imageData, forKey: key)
        } 
    }

    para establecer la imagen como fondo en settingsVC he utilizado el código de abajo.

    let croppedImage = cropImage(selectedImage, toRect: rect, viewWidth: self.view.bounds.size.width, viewHeight: self.view.bounds.size.width)
    
    imageDefaults.setImage(image: croppedImage, forKey: "imageDefaults")

    en mainVC :

    let bgImage = imageDefaults.imageForKey(key: "imageDefaults")!
  6. 5

    Sí , técnicamente es posible como en el

    [[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:@"foo"];

    Pero no es aconsejable porque plists no son lugares apropiados para grandes bloques de datos binarios especialmente User Prefs. Sería mejor guardar la imagen de usuario carpeta docs y almacenar la referencia a ese objeto como una dirección URL o ruta de acceso.

  7. 3

    De la documentación de apple,

    La NSUserDefaults clase proporciona métodos de conveniencia para acceder a los tipos comunes tales como flotadores, dobles, enteros, Booleanos, y las direcciones Url. Un objeto predeterminado debe ser una propiedad de la lista, es decir, una instancia de (o para colecciones de una combinación de las instancias de): NSData, NSString, NSNumber, NSDate, NSArray, o NSDictionary. Si desea almacenar cualquier tipo de objeto, normalmente, debe archivo para crear una instancia de NSData.

    Puede guardar imagen como esta:-

    [[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation([UIImage imageNamed:@"yourimage.gif"])forKey:@"key_for_your_image"];

    Y leer como este:-

     NSData* imageData = [[NSUserDefaults standardUserDefaults]objectForKey:@"key_for_your_image"];
        UIImage* image = [UIImage imageWithData:imageData];
  8. 3

    Para Swift 3 y JPG formato

    Registro Predeterminado De La Imagen :

    UserDefaults.standard.register(defaults: ["key":UIImageJPEGRepresentation(image, 100)!])

    Guardar Imagen :

    UserDefaults.standard.set(UIImageJPEGRepresentation(image, 100), forKey: "key")

    Cargar La Imagen :

    let imageData = UserDefaults.standard.value(forKey: "key") as! Data
    let imageFromData = UIImage(data: imageData)!
  9. 2

    Es técnicamente posible, pero no es recomendable. Guardar la imagen de disco en su lugar. NSUserDefaults está destinado a pequeños, no grandes archivos de datos binarios.

  10. 1

    Guardar la imagen para NSUserDefault:

    NSData *imageData; 
    //create NSData-object from image
    imageData = UIImagePNGRepresentation([dic objectForKey:[NSString stringWithFormat:@"%d",i]]); 
    //save NSData-object to UserDefaults
    [[NSUserDefaults standardUserDefaults] setObject:imageData forKey:[NSString stringWithFormat:@"%d",i]];

    Cargar la Imagen de NSUserDefault:

    NSData *imageData;
    //Load NSData-object from NSUserDefault
    imageData = [[NSUserDefaults standardUserDefaults] valueForKey:[NSString stringWithFormat:@"%d",i]];
    //get Image from NSData
    [image setObject:[UIImage imageWithData:imageData] forKey:[NSString stringWithFormat:@"%d",i]];
  11. 1

    Sí, usted puede utilizar. Pero ya que es para el almacenamiento de las preferencias, puede guardar las imágenes a la carpeta de documentos.

    Y usted puede tener la ruta de acceso en el NSUserDefaults, si es necesario.

  12. 1

    Ya que esta pregunta tiene un alto índice de búsqueda de google – aquí está @NikitaTook la respuesta en el día de hoy y la edad, es decir, Swift 3 y 4 (con excepciones).

    Nota: Esta clase es el único escrito a leer y escribir imágenes de formato JPG para el sistema de ficheros. El Userdefaults cosas deben ser manejados fuera de ella.

    writeFile lleva en el nombre del archivo de imagen jpg (con .extensión jpg) y el UIImage sí mismo y devuelve true si es capaz de guardar o de lo contrario devuelve false si no se puede escribir la imagen, momento en el que puede guardar la imagen en Userdefaults que sería su plan de copia de seguridad o simplemente reintentar una vez más. El readFile función toma en el nombre de archivo de imagen y devuelve un UIImage, si el nombre de la imagen que se pasan a esta función se encuentra, a continuación, devuelve la imagen de lo contrario sólo devuelve un valor predeterminado de marcador de posición de imagen de la aplicación de la carpeta de recursos (de esta manera usted puede evitar desagradables accidentes u otros extraños comportamientos).

    import Foundation
    import UIKit
    
    class ReadWriteFileFS{
    
        func writeFile(_ image: UIImage, _ imgName: String) -> Bool{
            let imageData = UIImageJPEGRepresentation(image, 1)
            let relativePath = imgName
            let path = self.documentsPathForFileName(name: relativePath)
    
            do {
                try imageData?.write(to: path, options: .atomic)
            } catch {
                return false
            }
            return true
        }
    
        func readFile(_ name: String) -> UIImage{
            let fullPath = self.documentsPathForFileName(name: name)
            var image = UIImage()
    
            if FileManager.default.fileExists(atPath: fullPath.path){
                image = UIImage(contentsOfFile: fullPath.path)!
            }else{
                image = UIImage(named: "user")!  //a default place holder image from apps asset folder
            }
            return image
        }
    }
    
    extension ReadWriteFileFS{
        func documentsPathForFileName(name: String) -> URL {
            let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            let path = paths[0]
            let fullPath = path.appendingPathComponent(name)
            return fullPath
        }
    }

Dejar respuesta

Please enter your comment!
Please enter your name here