Чи можна зберегти зображення NSUserDefaults
як об'єкт, а потім отримати для подальшого використання?
Відповіді:
УВАГА! ЯКЩО ви працюєте під iOS8 / XCODE6, ДИВІТЬСЯ МОЄ ОНОВЛЕННЯ нижче
Для тих, хто все ще шукає відповіді, тут є код "доцільного" способу збереження зображення в NSUserDefaults. Ви НЕ ПОВИННІ зберігати дані зображень безпосередньо в NSUserDefaults!
Запис даних:
// 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];
Зчитування даних:
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];
}
Для iOS8 / XCODE6 Оскільки tmr та DevC згадані в коментарях нижче, існує проблема з xcode6 / ios8. Різниця між процесом встановлення xcode5 та xcode 6 полягає в тому, що xcode6 змінює UUID додатків після кожного запуску в xcode (див. Виділену частину шляху: / var / mobile / Containers / Data / Application / B0D49CF5-8FBE-4F14-87AE-FA8C16A678B1 / Documents / image.jpg).
Отже, є 2 обхідних шляхи:
Ось швидка версія коду як бонус (з 2-м підходом):
Запис даних:
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()
Зчитування даних:
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
}
Щоб зберегти зображення в NSUserDefaults:
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:key];
Щоб отримати зображення з NSUserDefaults:
NSData* imageData = [[NSUserDefaults standardUserDefaults] objectForKey:key];
UIImage* image = [UIImage imageWithData:imageData];
Незважаючи на те, що можна зберегти UIImage
до NSUserDefaults
, це часто не рекомендується, оскільки це не найефективніший спосіб збереження зображень; більш ефективний спосіб - зберегти зображення у програмі Documents Directory
.
Для цілей цього запитання я додав відповідь на ваше запитання разом із більш ефективним способом збереження UIImage
.
Збереження в NSUserDefaults
Цей метод дозволяє зберігати будь- UIImage
які 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];
}
Ось як ви це називаєте:
[self saveImageToUserDefaults:image ofType:@"jpg" forKey:@"myImage"];
[[NSUserDefaults standardUserDefaults] synchronize];
Завантаження з NSUserDefaults
Цей метод дозволяє завантажувати будь-які UIImage
з NSUserDefaults
.
-(UIImage *)loadImageFromUserDefaultsForKey:(NSString *)key {
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
return [UIImage imageWithData:[userDefaults objectForKey:key]];
}
Ось як ви це називаєте:
UIImage * image = [self loadImageFromUserDefaultsForKey:@"myImage"];
Збереження до каталогу документів
Цей метод дозволяє зберігати будь- UIImage
які Documents Directory
файли в додатку.
-(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);
}
}
Ось як ви це називаєте:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[self saveImage:image withFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Завантаження з каталогу документів
Цей метод дозволяє завантажувати будь-яку UIImage
з програми Documents Directory
.
-(UIImage *)loadImageWithFileName:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.%@", directoryPath, fileName, [extension lowercaseString]]];
return result;
}
Ось як ви це називаєте:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * image = [self loadImageWithFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Збереження UIImage у бібліотеці фотографій
Цей метод дозволяє зберігати будь- UIImage
які дані на пристрої Photo Library
і називається таким чином:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
Збереження декількох зображень UII у бібліотеці фотографій
Цей метод дозволяє зберегти кілька UIImages
на пристрої 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);
}
}
Ось як ви це називаєте:
[self saveImagesToPhotoAlbums:images];
Де images
ваша NSArray
складається з UIImages
.
inDirectory:(NSString *)directoryPath
- чи можете ви просто назвати його як завгодно, як "myAppData" ??
Для Свіфта 4
Я майже все спробував у цьому питанні, але для мене ніхто не працює. і я знайшов своє рішення. спочатку я створив розширення для UserDefaults, як показано нижче, а потім просто викликав методи get and 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)
}
}
щоб встановити зображення як фон у налаштуваннях ВК я використовував код нижче.
let croppedImage = cropImage(selectedImage, toRect: rect, viewWidth: self.view.bounds.size.width, viewHeight: self.view.bounds.size.width)
imageDefaults.setImage(image: croppedImage, forKey: "imageDefaults")
в mainVC:
let bgImage = imageDefaults.imageForKey(key: "imageDefaults")!
Для швидких 2.2
Зберігати:
NSUserDefaults.standardUserDefaults().setObject(UIImagePNGRepresentation(chosenImage), forKey: kKeyImage)
Щоб отримати:
if let imageData = NSUserDefaults.standardUserDefaults().objectForKey(kKeyImage),
let image = UIImage(data: imageData as! NSData){
// use your image here...
}
Так, технічно можливо, як у
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:@"foo"];
Але не доцільно, тому що списки не є відповідними місцями для великих крапок двійкових даних, особливо User Prefs. Було б краще зберегти зображення в папці документів користувача та зберегти посилання на цей об'єкт як URL-адресу або шлях.
Для Swift 3 та JPG формату
Зареєструвати зображення за замовчуванням:
UserDefaults.standard.register(defaults: ["key":UIImageJPEGRepresentation(image, 100)!])
Зберегти зображення :
UserDefaults.standard.set(UIImageJPEGRepresentation(image, 100), forKey: "key")
Завантажити зображення:
let imageData = UserDefaults.standard.value(forKey: "key") as! Data
let imageFromData = UIImage(data: imageData)!
З документації Apple,
Клас NSUserDefaults забезпечує зручні методи доступу до загальних типів, таких як плаваючі, подвійні, цілі числа, логічні значення та URL-адреси. Об'єктом за замовчуванням повинен бути список властивостей, тобто екземпляр (або для колекцій комбінація екземплярів): NSData, NSString, NSNumber, NSDate, NSArray або NSDictionary. Якщо ви хочете зберегти будь-який інший тип об'єкта, вам, як правило, слід архівувати його, щоб створити екземпляр NSData.
Ви можете зберегти зображення таким чином: -
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation([UIImage imageNamed:@"yourimage.gif"])forKey:@"key_for_your_image"];
І читайте так: -
NSData* imageData = [[NSUserDefaults standardUserDefaults]objectForKey:@"key_for_your_image"];
UIImage* image = [UIImage imageWithData:imageData];
Це технічно можливо, але це недоцільно. Збережіть зображення на диск. NSUserDefaults призначений для невеликих налаштувань, а не великих файлів двійкових даних.
Зберегти зображення в 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]];
Завантажити зображення з 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]];
Оскільки це запитання має високий індекс пошуку Google - ось відповідь @ NikitaTook у сьогоднішній день і вік, тобто Swift 3 та 4 (за винятком обробки).
Примітка: Цей клас призначений виключно для читання та запису зображень у форматі JPG у файлову систему. Userdefaults
Матеріал слід звертатися за її межами.
writeFile
приймає ім'я файлу вашого jpg-зображення (із розширенням .jpg) і UIImage
саме, і повертає true, якщо він може зберегти, або повертає false, якщо він не може записати зображення, після чого ви можете зберегти зображення, в Userdefaults
якому буде вашим планом резервного копіювання або просто повторіть спробу ще раз. readFile
Функція приймає ім'я файлу зображення і повертає UIImage
, якщо ім'я зображення передається цій функція знайдено , то він повертає цей образ ще він просто повертає заміщає зображення по замовчуванням з папки активів програми (таким чином , ви можете уникнути неприємних аварій або інші дивна поведінка).
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
}
}
Свіфт 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
}