正如标题所说,我试图在用户默认情况下保存一个带有一些UIImages的NSDictionary:
UIImage* img = PhotoView.image;
NSMutableDictionary *UserInfoDictionary = [[NSMutableDictionary alloc] init];
[UserInfoDictionary setObject:img forKey:@"ProfileImage"];
[UserInfoDictionary setObject:ProfileUsername.text forKey:@"Username"];
[[NSUserDefaults standardUserDefaults] setObject:UserInfoDictionary forKey:@"ProfileAndFolderInformation"];
字典中最多可添加30张图片,但现在应用程序因错误而崩溃:
Attempt to set a non-property-list object {
ProfileImage = "<UIImage: 0x16dc4280>";
} as an NSUserDefaults value for key ProfileAndFolderInformation
2013-11-23 21:39:00.261 Cleverly[363:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object {
ProfileImage = "<UIImage: 0x16dc4280>";
} for key ProfileAndFolderInformation'
*** First throw call stack:
(0x30b59e83 0x3aeba6c7 0x30b59dc5 0x3148aa91 0xbaad9 0x33312da3 0x33312d3f 0x33312d13 0x332fe743 0x3331275b 0x33312425 0x3330d451 0x332e2d79 0x332e1569 0x30b24f1f 0x30b243e7 0x30b22bd7 0x30a8d471 0x30a8d253 0x357c12eb 0x33342845 0x9bb7d 0x3b3b3ab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
甚至可以在用户默认值下存储图像吗?
答案 0 :(得分:2)
您需要将映像序列化到磁盘,然后在用户默认值中指向该文件。 UIImage
符合NSCoding
协议,因此您可以使用NSKeyedArchiver
和NSKeyedUnarchiver
序列化图片数据,也可以使用UIImagePNGRepresentation
将图片转换为PNG并保存,但效率较低。
答案 1 :(得分:2)
直接在NSUserDefaults
中存储图像是不可能的,因为例外情况说,UIImage
不是属性列表对象。属性列表是这些对象的组合,只有这些类(或其子类):
NSArray
NSDictionary
NSString
NSData
NSDate
NSNumber
例如,您可以使用NSUserDefaults
来存储NSArray
个NSString
个对象。
从技术上讲,您可以通过将NSData
转换为JPEG,PNG或其他标准文件格式来创建UIImage
对象,然后将其存储在NSUserDefaults中,如下所示:
UIImage *image = ... ; // your image
CGFloat compressionQuality = 0.8; // the amount of compression, 1.0 being the lowest
NSData *imageData = UIImageJPEGRepresentation(image, compressionQuality);
[[NSUserDefaults standardUserDefaults] setObject:imageData forKey:@"key"];
但你真的不应该这样做。使用UIImageJPEGRepresentation
:
UIImage *image = ... ; // your image
CGFloat compressionQuality = 0.8; // the amount of compression, 1.0 being the lowest
NSData *imageData = UIImageJPEGRepresentation(image, compressionQuality);
// Get the directories you can write to
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// Get the first one
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
NSString *uniqueSuffix = @"something";
NSString *path = [documentDirectory stringByAppendingString:uniqueSuffix];
[imageData writeToFile:path atomically:YES]; // atomically is a bit safer, but slower
或者你可以从UIImage实现NSCoding协议的事实中受益:
@interface TestImageStore () <NSCoding>
@property (strong, nonatomic) UIImage *image1;
@property (strong, nonatomic) UIImage *image2;
@end
@implementation TestImageStore
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.image1 = [aDecoder decodeObjectForKey:@"image1"];
self.image2 = [aDecoder decodeObjectForKey:@"image2"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.image1 forKey:@"image1"];
[aCoder encodeObject:self.image2 forKey:@"image2"];
}
最后,你也可以使用核心数据,但这肯定比上面概述的方法更复杂。
答案 2 :(得分:1)
您只能在NSUserdefaults
中保存一组有限的对象类型,UIImage
不是其中之一。我不知道NSUserDefaults
的大小限制。 UIImage
可以转换为可接受的类型,但请参见下文:
这实际上是在滥用NSUserDefaults
。将数据(序列化为数据)保存在文档目录的文件中,如有必要,将文件名保存在NSUserDefaults
中。但只是在NSUserDefaults中保存名称是不合适的,这就是CoreData或SQLite或其他文档所针对的目的。
来自Apple文档:
NSUserDefaults类提供了便于访问的方法 常见类型,例如浮点数,双精度数,整数,布尔值和URL。一个 默认对象必须是属性列表,即(或 对于集合的实例组合): NSData,NSString, NSNumber,NSDate,NSArray或NSDictionary 。如果你想存储任何 在其他类型的对象中,通常应将其存档以创建 NSData的实例。