2013-11-23 34 views
0

正如标题所说,我试图在用户默认设置一个NSDictionary节省一些UIImages在它:保存的NSDictionary与UIImage的用户默认

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 

它甚至可以存储用户默认图像?

回答

2

不可能直接在NSUserDefaults中存储图像,因为如例外所述,UIImage不是属性列表对象。一个属性列表是这些对象的组合,只有这些,类(或亚类的化合物):

  • NSArray
  • NSDictionary
  • NSString
  • NSData
  • NSDate
  • NSNumber

例如,您可以使用NSUserDefaults来存储NSString对象的NSArray

从技术上讲,你可以通过转换UIImage为JPEG,PNG,或其他标准文件格式创建NSData对象,然后将其存储在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 
N​S​A​r​r​a​y​ ​*​d​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​i​e​s​ ​=​ ​N​S​S​e​a​r​c​h​P​a​t​h​F​o​r​D​i​r​e​c​t​o​r​i​e​s​I​n​D​o​m​a​i​n​s​(​N​S​D​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​,​ N​S​U​s​e​r​D​o​m​a​i​n​M​a​s​k​, Y​E​S​)​;​ 
// Get the first one 
​N​S​S​t​r​i​n​g​ ​*​d​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​y​ ​=​ ​[​d​o​c​u​m​e​n​t​D​i​r​e​c​t​o​r​i​e​s​ ​o​b​j​e​c​t​A​t​I​n​d​e​x​:​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"]; 
} 

最后,你也可以使用核心数据,但这绝对比上述方法更复杂。

1

您只能在NSUserdefaults中保存一组有限的对象类型,UIImage不是其中之一。我不知道NSUserDefaults上的大小限制。 UIImage可以转换为可接受的类型,但看到如下:

这真的是滥用NSUserDefaults。将数据(序列化为数据)保存在文档目录中的文件中,必要时将文件名保存在NSUserDefaults中。但只是将名称保存在NSUserDefaults中是不恰当的,这就是CoreData或SQLite或其他文档方法的用处。

从Apple文档:

The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Booleans, and URLs. A default object must be a property list, that is, an instance of (or for collections a combination of instances of): NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. If you want to store any other type of object, you should typically archive it to create an instance of NSData.

2

您需要将图像序列化到磁盘,然后指向用户默认该文件。 UIImage符合NSCoding协议,因此您可以使用NSKeyedArchiverNSKeyedUnarchiver来序列化图像数据,或者您可以使用UIImagePNGRepresentation将图像转换为PNG并保存该图像,但效率较低。