¿Es posible guardar imágenes NSUserDefaults
como un objeto y luego recuperarlas para su uso posterior?
¡ATENCIÓN! SI ESTÁ TRABAJANDO CON iOS8 / XCODE6, VER MI ACTUALIZACIÓN A CONTINUACIÓN
Para aquellos que todavía buscan una respuesta, aquí hay un código de forma "recomendable" para guardar la imagen en NSUserDefaults. ¡NO DEBE guardar datos de imágenes 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];
Leer 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 se mencionan en los comentarios a continuación, hay un problema con xcode6 / ios8. La diferencia entre el proceso de instalación de xcode5 y xcode 6 es que xcode6 cambia el UUID de las aplicaciones después de cada ejecución en xcode (consulte la parte resaltada en la ruta: / var / mobile / Containers / Data / Application / B0D49CF5-8FBE-4F14-87AE-FA8C16A678B1 / Documents / image.jpg).
Entonces hay 2 soluciones alternativas:
Aquí hay una versión rápida del código como un bono (con un segundo 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()
Leer 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
}
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];
fuente
Si bien es posible guardar un
UIImage
enNSUserDefaults
, a menudo no se recomienda ya que no es la forma más eficiente de guardar imágenes; una forma más eficiente es guardar su imagen en la aplicaciónDocuments Directory
.A los efectos de esta pregunta, he adjuntado la respuesta a su pregunta, junto con la forma más eficiente de guardar un archivo
UIImage
.NSUserDefaults (no recomendado)
Guardar en NSUserDefaults
Este método le permite guardar cualquier
UIImage
archivoNSUserDefaults
.-(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]; }
Así es como lo llamas:
[self saveImageToUserDefaults:image ofType:@"jpg" forKey:@"myImage"]; [[NSUserDefaults standardUserDefaults] synchronize];
Cargando desde NSUserDefaults
Este método le permite cargar cualquier
UIImage
archivoNSUserDefaults
.-(UIImage *)loadImageFromUserDefaultsForKey:(NSString *)key { NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults]; return [UIImage imageWithData:[userDefaults objectForKey:key]]; }
Así es como lo llamas:
UIImage * image = [self loadImageFromUserDefaultsForKey:@"myImage"];
Una mejor alternativa
Guardar en el directorio de documentos
Este método le permite guardar cualquier
UIImage
a laDocuments 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); } }
Así es como lo llamas:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; [self saveImage:image withFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Cargando desde el directorio de documentos
Este método le permite cargar cualquier archivo
UIImage
de la aplicaciónDocuments Directory
.-(UIImage *)loadImageWithFileName:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath { UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.%@", directoryPath, fileName, [extension lowercaseString]]]; return result; }
Así es como lo llamas:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; UIImage * image = [self loadImageWithFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Una alternativa diferente
Guardar UIImage en la biblioteca de fotos
Este método le permite guardar cualquiera
UIImage
en el dispositivoPhoto Library
y se llama de la siguiente manera:UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
Guardar múltiples imágenes de UII en la biblioteca de fotos
Este método le permite guardar varios archivos
UIImages
en el dispositivoPhoto 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); } }
Así es como lo llamas:
[self saveImagesToPhotoAlbums:images];
¿De dónde
images
está tuNSArray
compuestoUIImages
?fuente
inDirectory:(NSString *)directoryPath
? ¿Podrías llamarlo como quieras, como "myAppData"?Para Swift 4
Casi probé todo en esta pregunta, pero nadie me funcionó. y encontré mi solución. Primero creé una extensión para UserDefaults como a continuación, luego llamé a los 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 configurar la imagen como fondo en settingsVC utilicé el siguiente código.
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")!
fuente
Para swift 2.2
Para almacenar:
NSUserDefaults.standardUserDefaults().setObject(UIImagePNGRepresentation(chosenImage), forKey: kKeyImage)
Para recuperar:
if let imageData = NSUserDefaults.standardUserDefaults().objectForKey(kKeyImage), let image = UIImage(data: imageData as! NSData){ // use your image here... }
fuente
Sí, técnicamente posible como en
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:@"foo"];
Pero no es aconsejable porque los plists no son lugares apropiados para grandes cantidades de datos binarios, especialmente User Prefs. Sería mejor guardar la imagen en la carpeta de documentos del usuario y almacenar la referencia a ese objeto como una URL o ruta.
fuente
Para Swift 3 y JPG formato
Registrar imagen predeterminada:
UserDefaults.standard.register(defaults: ["key":UIImageJPEGRepresentation(image, 100)!])
Guardar imagen :
UserDefaults.standard.set(UIImageJPEGRepresentation(image, 100), forKey: "key")
Cargar imagen :
let imageData = UserDefaults.standard.value(forKey: "key") as! Data let imageFromData = UIImage(data: imageData)!
fuente
De la documentación de Apple,
Puede guardar una imagen como esta: -
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation([UIImage imageNamed:@"yourimage.gif"])forKey:@"key_for_your_image"];
Y lea así: -
NSData* imageData = [[NSUserDefaults standardUserDefaults]objectForKey:@"key_for_your_image"]; UIImage* image = [UIImage imageWithData:imageData];
fuente
Es técnicamente posible, pero no es recomendable. En su lugar, guarde la imagen en el disco. NSUserDefaults está diseñado para configuraciones pequeñas, no grandes archivos de datos binarios.
fuente
Guardar imagen en 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 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]];
fuente
Sí, puedes usar. Pero como es para el almacenamiento de preferencias, puede guardar mejor las imágenes en la carpeta de documentos.
Y puede tener la ruta en el
NSUserDefaults
, si es necesario.fuente
Dado que esta pregunta tiene un alto índice de búsqueda en Google, aquí está la respuesta de @ NikitaTook en la época actual, es decir, Swift 3 y 4 (con manejo de excepciones).
Nota: Esta clase está escrita únicamente para leer y escribir imágenes de formato JPG en el sistema de archivos. Las
Userdefaults
cosas deben manipularse fuera de él.writeFile
toma el nombre de archivo de su imagen jpg (con extensión .jpg) y elUIImage
mismo y devuelve verdadero si puede guardar o devuelve falso si no puede escribir la imagen, momento en el que puede almacenar la imagen en laUserdefaults
que sería su plan de respaldo o simplemente vuelva a intentarlo una vez más. LareadFile
función toma el nombre del archivo de imagen y devuelve unUIImage
, si se encuentra el nombre de la imagen pasado a esta función, entonces devuelve esa imagen; de lo contrario, solo devuelve una imagen de marcador de posición predeterminada de la carpeta de activos de la aplicación (de esta manera puede evitar bloqueos desagradables u otros comportamientos extraños).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 } }
fuente
Swift 4.x
Xcode 11.x
func saveImageInUserDefault(img:UIImage, key:String) { UserDefaults.standard.set(img.pngData(), forKey: key) } func getImageFromUserDefault(key:String) -> UIImage? { let imageData = UserDefaults.standard.object(forKey: key) as? Data var image: UIImage? = nil if let imageData = imageData { image = UIImage(data: imageData) } return image }
fuente