versiones programar playgrounds developers curso aprender ios objective-c iphone swift ipad

ios - programar - swift playgrounds iphone



Guardar imágenes en NSUserDefaults? (12)

¿Es posible guardar imágenes en NSUserDefaults como un objeto y luego recuperarlas para un uso posterior?


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

Nota: Esta clase está escrita exclusivamente para leer y escribir imágenes de formato JPG en el sistema de archivos. Las cosas de Userdefaults deben manejarse fuera de él.

writeFile toma el nombre de archivo de su imagen jpg (con extensión .jpg) y el UIImage mismo y devuelve true si es capaz de guardar o devuelve falso si no puede escribir la imagen, en ese momento puede almacenar la imagen en Userdefaults que sería su plan de respaldo o simplemente Userdefaults intentarlo una vez más. La función readFile toma el nombre del archivo de imagen y devuelve un UIImage , si se encuentra el nombre de la imagen transferido a esta función, devuelve esa imagen, sino que 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 otras conductas extrañas).

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


De la documentación de apple,

La clase NSUserDefaults proporciona métodos prácticos para acceder a tipos comunes como flotantes, dobles, enteros, booleanos y URL. Un objeto predeterminado debe ser una lista de propiedades, es decir, una instancia de (o para colecciones una combinación de instancias de): NSData, NSString, NSNumber, NSDate, NSArray o NSDictionary. Si desea almacenar cualquier otro tipo de objeto, normalmente debe archivarlo para crear una instancia de NSData.

Puede guardar una imagen como esta:

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

Y lee así: -

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


Es técnicamente posible, pero no es aconsejable. Guarde la imagen en el disco en su lugar. NSUserDefaults está diseñado para configuraciones pequeñas, no grandes archivos de datos binarios.


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


Para Swift 3 y formato JPG

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


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


Sí, puedes usar Pero dado que es para almacenar las preferencias, puede guardar mejor las imágenes en la carpeta del documento.

Y puede tener la ruta en NSUserDefaults , si es necesario.


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 Prefs de usuario. 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.


Si bien es posible guardar un UIImage a NSUserDefaults , 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 el Documents Directory la aplicación.

A los fines de esta pregunta, adjunté la respuesta a su pregunta, junto con la forma más eficiente de guardar un UIImage .

NSUserDefaults (No recomendado)

Guardar en 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]; }

Así es como lo llamas:

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

Cargando desde NSUserDefaults

Este método te permite cargar cualquier UIImage desde NSUserDefaults .

-(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 te permite guardar cualquier UIImage en el 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); } }

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 UIImage desde el Documents Directory de la aplicación.

-(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

Guardando UIImagel en la Biblioteca de fotos

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

UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);

Guardar múltiples UIImages en Photo Library

Este método te permite guardar varios UIImages en la Photo Library del dispositivo.

-(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];

Where images es tu NSArray compuesto por UIImages .


¡ATENCIÓN! SI TRABAJA BAJO iOS8 / XCODE6 VEA MI ACTUALIZACIÓN A CONTINUACIÓN

Para aquellos que aún 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 (vea parte destacada en la ruta: / var / mobile / Containers / Data / Application / B0D49CF5-8FBE-4F14-87AE-FA8C16A678B1 / Documents / image.jpg).

Entonces hay 2 soluciones:

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

Aquí hay una versión rápida del código como una bonificación (con el 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 Swift 4

Casi lo intenté todo en esta pregunta, pero nadie se trabajó para mí. y encontré mi solución. primero, creé una extensión para UserDefaults como a continuación, y luego llamé a get y set methods.

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 utilicé el código a continuación.

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")!


Para veloz 2.2

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