Có thể lưu hình ảnh thành NSUserDefaults
một đối tượng và sau đó truy xuất để sử dụng tiếp không?
Câu trả lời:
CHÚ Ý! NẾU BẠN ĐANG LÀM VIỆC DƯỚI iOS8 / XCODE6, XEM BẢN CẬP NHẬT CỦA TÔI BÊN DƯỚI
Đối với những người vẫn đang tìm kiếm câu trả lời, đây là mã của cách "khuyến khích" để lưu hình ảnh trong NSUserDefaults. Bạn KHÔNG NÊN lưu dữ liệu hình ảnh trực tiếp vào NSUserDefaults!
Ghi dữ liệu:
// 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];
Đọc dữ liệu:
NSString *imagePath = [[NSUserDefaults standardUserDefaults] objectForKey:kPLDefaultsAvatarUrl];
if (imagePath) {
self.avatarImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath]];
}
documentPathForFileName:
- (NSString *)documentsPathForFileName:(NSString *)name {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
return [documentsPath stringByAppendingPathComponent:name];
}
Đối với iOS8 / XCODE6 Như tmr và DevC đã đề cập trong nhận xét bên dưới, có vấn đề với xcode6 / ios8. Sự khác biệt giữa quá trình cài đặt xcode5 và xcode 6 là xcode6 thay đổi UUID ứng dụng sau mỗi lần chạy trong xcode (xem phần được tô sáng trong đường dẫn: / var / mobile / Containers / Data / Application / B0D49CF5-8FBE-4F14-87AE-FA8C16A678B1 / Documents / image.jpg).
Vì vậy, có 2 cách giải quyết:
Đây là phiên bản mã nhanh như một phần thưởng (với cách tiếp cận thứ 2):
Ghi dữ liệu:
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()
Đọc dữ liệu:
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)
}
documentPathForFileName:
func documentsPathForFileName(name: String) -> String {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true);
let path = paths[0] as String;
let fullPath = path.stringByAppendingPathComponent(name)
return fullPath
}
Để lưu hình ảnh trong NSUserDefaults:
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:key];
Để truy xuất hình ảnh từ NSUserDefaults:
NSData* imageData = [[NSUserDefaults standardUserDefaults] objectForKey:key];
UIImage* image = [UIImage imageWithData:imageData];
Mặc dù có thể lưu một UIImage
đến NSUserDefaults
, nhưng nó thường không được khuyến khích vì nó không phải là cách hiệu quả nhất để lưu hình ảnh; một cách hiệu quả hơn là lưu hình ảnh của bạn trong ứng dụng Documents Directory
.
Với mục đích của câu hỏi này, tôi đã đính kèm câu trả lời cho câu hỏi của bạn, cùng với cách tiết kiệm hiệu quả hơn a UIImage
.
Lưu vào NSUserDefaults
Phương pháp này cho phép bạn lưu bất kỳ UIImage
vào 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];
}
Đây là cách bạn gọi nó:
[self saveImageToUserDefaults:image ofType:@"jpg" forKey:@"myImage"];
[[NSUserDefaults standardUserDefaults] synchronize];
Đang tải từ NSUserDefaults
Phương pháp này cho phép bạn tải bất kỳ UIImage
từ nào NSUserDefaults
.
-(UIImage *)loadImageFromUserDefaultsForKey:(NSString *)key {
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
return [UIImage imageWithData:[userDefaults objectForKey:key]];
}
Đây là cách bạn gọi nó:
UIImage * image = [self loadImageFromUserDefaultsForKey:@"myImage"];
Lưu vào Thư mục Tài liệu
Phương pháp này cho phép bạn lưu bất kỳ UIImage
vào Documents Directory
bên trong ứng dụng.
-(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);
}
}
Đây là cách bạn gọi nó:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
[self saveImage:image withFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Tải từ thư mục tài liệu
Phương pháp này cho phép bạn tải bất kỳ UIImage
từ ứng dụng nào Documents Directory
.
-(UIImage *)loadImageWithFileName:(NSString *)fileName ofType:(NSString *)extension inDirectory:(NSString *)directoryPath {
UIImage * result = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.%@", directoryPath, fileName, [extension lowercaseString]]];
return result;
}
Đây là cách bạn gọi nó:
NSString * documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
UIImage * image = [self loadImageWithFileName:@"Ball" ofType:@"jpg" inDirectory:documentsDirectory];
Lưu UIImage vào Thư viện Ảnh
Phương pháp này cho phép bạn lưu bất kỳ tệp nào UIImage
vào thiết bị Photo Library
và được gọi như sau:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
Lưu nhiều ảnh UII vào Thư viện ảnh
Phương pháp này cho phép bạn lưu nhiều UIImages
vào thiết bị 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);
}
}
Đây là cách bạn gọi nó:
[self saveImagesToPhotoAlbums:images];
Của images
bạn NSArray
bao gồm đâu UIImages
.
inDirectory:(NSString *)directoryPath
- bạn có thể gọi nó bất cứ thứ gì bạn muốn như "myAppData" không ??
Đối với Swift 4
Tôi gần như đã thử mọi thứ trong câu hỏi này nhưng không ai phù hợp với tôi. và tôi đã tìm ra giải pháp của mình. đầu tiên tôi tạo một phần mở rộng cho UserDefaults như bên dưới, sau đó chỉ cần gọi các phương thức get và 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)
}
}
để đặt hình ảnh làm nền trong cài đặt, tôi đã sử dụng mã bên dưới.
let croppedImage = cropImage(selectedImage, toRect: rect, viewWidth: self.view.bounds.size.width, viewHeight: self.view.bounds.size.width)
imageDefaults.setImage(image: croppedImage, forKey: "imageDefaults")
trong mainVC:
let bgImage = imageDefaults.imageForKey(key: "imageDefaults")!
Đối với nhanh chóng 2.2
Để lưu trữ:
NSUserDefaults.standardUserDefaults().setObject(UIImagePNGRepresentation(chosenImage), forKey: kKeyImage)
Lấy:
if let imageData = NSUserDefaults.standardUserDefaults().objectForKey(kKeyImage),
let image = UIImage(data: imageData as! NSData){
// use your image here...
}
Có, về mặt kỹ thuật có thể như trong
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation(image) forKey:@"foo"];
Nhưng không nên vì plists không phải là nơi thích hợp cho các đốm màu lớn của dữ liệu nhị phân, đặc biệt là User Prefs. Sẽ tốt hơn nếu lưu hình ảnh vào thư mục tài liệu của người dùng và lưu trữ tham chiếu đến đối tượng đó dưới dạng URL hoặc đường dẫn.
Đối với Swift 3 và định dạng JPG
Đăng ký Hình ảnh Mặc định:
UserDefaults.standard.register(defaults: ["key":UIImageJPEGRepresentation(image, 100)!])
Lưu hình ảnh :
UserDefaults.standard.set(UIImageJPEGRepresentation(image, 100), forKey: "key")
Tải hình ảnh :
let imageData = UserDefaults.standard.value(forKey: "key") as! Data
let imageFromData = UIImage(data: imageData)!
Từ tài liệu của apple,
Lớp NSUserDefaults cung cấp các phương thức thuận tiện để truy cập các kiểu phổ biến như float, double, integer, Boolean và URL. Đối tượng mặc định phải là một danh sách thuộc tính, nghĩa là, một thể hiện của (hoặc đối với bộ sưu tập kết hợp các thể hiện của): NSData, NSString, NSNumber, NSDate, NSArray hoặc NSDictionary. Nếu bạn muốn lưu trữ bất kỳ loại đối tượng nào khác, thông thường bạn nên lưu trữ nó để tạo một phiên bản NSData.
Bạn có thể lưu hình ảnh như sau: -
[[NSUserDefaults standardUserDefaults] setObject:UIImagePNGRepresentation([UIImage imageNamed:@"yourimage.gif"])forKey:@"key_for_your_image"];
Và đọc như thế này: -
NSData* imageData = [[NSUserDefaults standardUserDefaults]objectForKey:@"key_for_your_image"];
UIImage* image = [UIImage imageWithData:imageData];
Về mặt kỹ thuật thì có thể, nhưng không nên. Thay vào đó, hãy lưu hình ảnh vào đĩa. NSUserDefaults dành cho các cài đặt nhỏ, không phải tệp dữ liệu nhị phân lớn.
Lưu hình ảnh vào 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]];
Tải hình ảnh từ 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]];
Có, bạn có thể sử dụng. Nhưng vì nó là để lưu trữ các tùy chọn, bạn có thể lưu hình ảnh tốt hơn vào thư mục tài liệu.
Và bạn có thể có đường dẫn trong NSUserDefaults
, nếu được yêu cầu.
Vì câu hỏi này có chỉ số tìm kiếm google cao - đây là câu trả lời của @ NikitaTook trong thời đại ngày nay, tức là Swift 3 và 4 (có xử lý ngoại lệ).
Lưu ý: Lớp này chỉ được viết để đọc và ghi hình ảnh có định dạng JPG vào hệ thống tệp. Những Userdefaults
thứ nên được xử lý bên ngoài nó.
writeFile
lấy tên tệp của hình ảnh jpg của bạn (với phần mở rộng .jpg) và UIImage
chính nó và trả về true nếu nó có thể lưu hoặc trả về false nếu nó không thể ghi hình ảnh, lúc này bạn có thể lưu trữ hình ảnh trong Userdefaults
đó sẽ là kế hoạch dự phòng của bạn hoặc đơn giản là thử lại một lần nữa. Các readFile
chức năng có trong tên tập tin hình ảnh và trả về một UIImage
, nếu tên hình ảnh thông qua chức năng này được tìm thấy sau đó nó sẽ trả về mà hình ảnh khác nó chỉ trả về một hình ảnh giữ chỗ mặc định từ thư mục tài sản của ứng dụng (theo cách này bạn có thể tránh tai nạn khó chịu hoặc khác hành vi kỳ lạ).
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
}
}
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
}