NSPropertyListSerialization
The NSPropertyListSerialization class provides methods that convert property list objects to and from several serialized formats. Property list objects include NSData, NSString, NSArray, NSDictionary, NSDate, and NSNumber objects. These objects are toll-free bridged with their respective Core Foundation types (CFData, CFString, and so on). For more about toll-free bridging, see “Interchangeable Data Types”.
NSPropertyListSerialization這個類提供了一些方法,專門用來轉換不同組織形式的list對象.list對象包括了NSData, NSString, NSArray, NSDictionary, NSDate, 以及 NSNumber.這些對象與衍生出他們的祖先對象有着一些聯系,對於toll-free bridging,請看“Interchangeable Data Types”.
大家都應該使用過NSCoding協議來持久化一個對象,但你試着用NSCoding協議來持久化一個字典或者數組試一下.
問:為什么要持久化一個字典或者數組呢?
持久化一個字典或者數組,可以使用方法writeToFile:atomically:來寫文件,但是有一個問題,這個只能寫成plist文件,別人是可以通過明文來觀看的,我可不喜歡別人能看清楚我存儲了一些什么數據,你也是一樣對吧.為什么要持久化一個字典或者數組呢?在需要存儲的數據比較少時,此時又不需要數據庫那種麻煩的查表方式來更改數據,更不需要CoreData這種大炮來打蚊子,所以,將數據存儲於一個字典或者數組中便於維護以及輕量級,但是存儲后成了plist文件,別人可以看到怎么辦?那就把它存儲成加密的NSData吧.
注:使用NSCoding協議是可以實現存儲字典的,但是,那代碼量你可以上網搜索一下解決方案,讓人望而卻步,本人在這里推薦使用下面的一個類NSPropertyListSerialization來處理字典或者數組的本地加密持久化,省掉你無數的代碼.
使用非常簡單,如下圖所示:
注意:生成的NSData要記得進行加密后存儲,提出出NSData時也需要進行解密操作后提取出來,推薦使用Des加密,看看有多簡單.
附錄:
經過本人一小時奮戰,將NSPropertyListSerialization進行簡易封裝,附帶源碼以及使用教程,隱藏了NSPropertyListSerialization實現細節.
ListObjectOperation.h + ListObjectOperation.m
// // ListObjectOperation.m // // Copyright (c) 2014年 Y.X. All rights reserved. // #import <Foundation/Foundation.h> /** 創建簡單的文件路徑 @param filePath 簡單的文件路徑,如 @"/Documents/Y.X." @return 完整的沙盒文件路徑 */ NS_INLINE NSString * simpleFilePath(NSString *filePath) { /* /Documents /Library/Caches /Library/Preferences /tmp */ return [NSHomeDirectory() stringByAppendingString:filePath]; } @interface ListObjectOperation : NSObject /** 將字典轉換為NSData后進行存儲 @param dictionary 字典 @param path 存儲的路徑 @return none */ + (void)storeDictionary:(NSDictionary *)dictionary toPath:(NSString *)path; /** 同步進行本地NSData以及字典同時操作 @param path 字典NSData的路徑 @param flag 是否存儲 @param dictionary block中的字典,如果flag為YES,則修改的list值會被保存,flag為NO,則修改的值不會同步保存 @return none */ + (void)syncDictionaryWithDataPath:(NSString *)path save:(BOOL)flag dictionary:(void (^)(NSMutableDictionary *list))dictionary; @end
// // ListObjectOperation.m // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "ListObjectOperation.h" NS_INLINE NSData * dataFromFileUrlPath(NSString *path) { return [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:path]]; } @implementation ListObjectOperation + (void)storeDictionary:(NSDictionary *)dictionary toPath:(NSString *)path { NSData *data = [[self class] dataWithListObject:dictionary]; [data writeToFile:path atomically:YES]; } + (void)syncDictionaryWithDataPath:(NSString *)path save:(BOOL)flag dictionary:(void (^)(NSMutableDictionary *list))dictionary { // 獲取字典 NSDictionary *dic = [[self class] listObjectWithdata:dataFromFileUrlPath(path)]; // 轉化為可變字典 NSMutableDictionary *changeDic = [NSMutableDictionary dictionaryWithDictionary:dic]; if (flag == YES) { // 傳入到字典中 dictionary(changeDic); // 生成二進制文件 NSData *data = [[self class] dataWithListObject:changeDic]; // 進行存儲(覆蓋了之前的文件) [data writeToFile:path atomically:YES]; } else { // 傳入到字典中 dictionary(changeDic); } } + (NSData *)dataWithListObject:(id)listObject { return [NSPropertyListSerialization dataWithPropertyList:listObject format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil]; } + (id)listObjectWithdata:(NSData *)data { return [NSPropertyListSerialization propertyListWithData:data options:0 format:NULL error:nil]; } @end
第一步:進行存儲操作(請君先執行一遍程序,生成一個二進制文件 .YouXianMing 存儲在沙盒的 /Document文件夾下)
第二步:同步修改字典以及存儲二進制文件(請君再一次運行程序)
第三步:驗證是否存儲進去了
擔心效率嗎?不用擔心,才2ms而已.實際上我測試了同時修改和存儲,也就3ms,輕量級存儲實在是太簡單了^_^.