2013-11-23 36 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並保存該圖像,但效率較低。