NSKeyedAchiver&NSKeyUnarchiver的封裝
- 歸檔和解歸檔是App數(shù)據(jù)持久化的方法之一滨溉。
- 歸檔和解歸檔用在遵循了NSCodying協(xié)議的對象什湘,比如說字典、數(shù)組晦攒、字符串等,但也可以把網(wǎng)絡(luò)請求的Json看做字典去存儲闽撤。
- 把歸檔,解歸檔和移除數(shù)據(jù)放在了一個工具類里面,創(chuàng)建的詳細(xì)過程見代碼的源文件
- .h文件中封裝的方法:
#import <Foundation/Foundation.h>
/**
* 必須NSCoding協(xié)議
*/
// 1.josn數(shù)據(jù)是字典格式 所以存起來毫無壓力啊
@interface LXKArchiverTool : NSObject
/**
* 歸檔對象
*
* @param object 歸檔對象
* @param keyString 歸檔的鍵
* @param pathString 已經(jīng)是Document路徑,只需加后綴
*/
+ (void)archiverObject:(id)object key:(NSString *)keyString filePath:(NSString *)pathString;
/**
* 解歸檔的對象
*
* @param pathString 已經(jīng)是Document路徑,只需加后綴
* @param keyStirng 歸檔的鍵
*
* @return 返回對象
*/
+ (id )unarchiverPath:(NSString *)pathString key:(NSString *)keyStirng;
/**
刪除歸檔的數(shù)據(jù)
@param pathString 已經(jīng)是Document路徑,只需加后綴
*/
+ (void)removeArchiverObjectFilePath:(NSString *)pathString;
@end
- .m文件中的實(shí)現(xiàn),里面有詳細(xì)的注釋,所以需要了解歸檔用解歸檔可以看一下注釋:
#import "LXKArchiverTool.h"
@implementation LXKArchiverTool
/**
* 歸檔對象
*
* @param object 歸檔對象
* @param keyString 歸檔的鍵
* @param pathString 已經(jīng)是Document路徑,只需加后綴
*/
+ (void)archiverObject:(id)object key:(NSString *)keyString filePath:(NSString *)pathString {
if (!object) {
NSLog(@"歸檔的對象為空");
return;
}
// NSMutableData對象相當(dāng)于一個數(shù)據(jù)中轉(zhuǎn)站 將遵循NSCoding協(xié)議的對象轉(zhuǎn)換為data數(shù)據(jù)
NSMutableData *mData = [NSMutableData data];
// 1.創(chuàng)建歸檔器
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:mData];
// 2.將對象進(jìn)行歸檔編碼并指定對應(yīng)的鍵
[archiver encodeObject:object forKey:keyString];
// 3.結(jié)束歸檔編碼
[archiver finishEncoding];
// 4.創(chuàng)建歸檔路徑
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
/**因?yàn)槲募窂皆谏澈?而斜杠(/)會被認(rèn)為是在下一個文件目錄下
但是我們并沒有建立這樣一個文件目錄 是所以要去除 避免歸檔失敗
其實(shí)吧 是因?yàn)橛辛?xí)慣把接口當(dāng)做路徑來存儲 有/會失敗 所以去出去*/
pathString = [pathString stringByReplacingOccurrencesOfString:@"/" withString:@""];
NSString *filePath = [path stringByAppendingPathComponent:pathString];
// 測試時間的時候請勿開啟打印
NSLog(@"歸檔的對象filePath == %@",filePath );
// 5. 寫入文件
[mData writeToFile:filePath atomically:YES];
}
/**
* 解歸檔的對象
*
* @param pathString 已經(jīng)是Document路徑,只需加后綴
* @param keyStirng 歸檔的鍵
*
* @return 返回對象
*/
+ (id )unarchiverPath:(NSString *)pathString key:(NSString *)keyStirng {
// 1. 建立解歸檔的路徑
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
pathString = [pathString stringByReplacingOccurrencesOfString:@"/" withString:@""];
NSString *filePath = [path stringByAppendingPathComponent:pathString];
// 2.根據(jù)路徑查找data數(shù)據(jù)
NSData *data = [NSData dataWithContentsOfFile:filePath];
// 3.創(chuàng)建解歸檔器
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
// 4. 取出解歸檔的對象
id object = [unarchiver decodeObjectForKey:keyStirng];
NSLog(@"解歸檔的對象filePath == %@",filePath );
if (!object) {
NSLog(@"解歸檔的對象為空或者路徑不對");
return nil;
}
// 通過指定的鍵將對象解歸檔出來
return object;
}
/**
刪除歸檔的數(shù)據(jù)
@param pathString 已經(jīng)是Document路徑,只需加后綴
*/
+ (void)removeArchiverObjectFilePath:(NSString *)pathString {
// 1.創(chuàng)建文件管理器
NSFileManager *defaultManager = [NSFileManager defaultManager];
// 2.查找刪除路徑
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
pathString = [pathString stringByReplacingOccurrencesOfString:@"/" withString:@""];
NSString *filePath = [path stringByAppendingPathComponent:pathString];
// 3. 如果此路徑下存在文件 刪除此路徑下的文件
if ([defaultManager isDeletableFileAtPath:filePath]) {
[defaultManager removeItemAtPath:filePath error:nil];
}
}
@end
使用和測試時間
補(bǔ)充小知識點(diǎn),測試一段代碼的時長
NSDate *startDate = [NSDate date];
// your code
double dealTime = [[NSDate date] timeIntervalSinceDate:startDate];
// 使用毫秒測試 1s = 1000ms
NSLog(@"codeTime === %f ms", dealTime * 1000);
測試時間
- 常常聽別人說歸檔與解歸檔使用與大文件并且不常用的文件使用,那我們來看一看存儲、讀取脯颜、刪除都花了多少時間吧哟旗,為此使用YYCahe來對比一下:
#import "LXKArchiverTool.h"
#import <YYCache.h>
@interface ViewController ()
@property (nonatomic, strong) NSMutableDictionary *responseObject; //想要存儲的數(shù)據(jù)
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_responseObject = [NSMutableDictionary dictionary];
for (NSInteger i = 0; i < 100; i++) {
[_responseObject setObject:[NSString stringWithFormat:@"test %ld",i] forKey:[NSString stringWithFormat:@"test %ld",i] ];
}
// 是路徑也是存儲的鍵
NSString *filePath = @"responseObject";
// 1.存儲時間
NSDate *tempStartDate = [NSDate date];
[LXKArchiverTool archiverObject:_responseObject key:filePath filePath:filePath];
[self endTimeLogStarDate:tempStartDate];
NSDate *temp2 = [NSDate date];
YYCache *yyCache = [YYCache cacheWithName:filePath];
[yyCache setObject:_responseObject forKey:filePath];
[self endTimeLogStarDate:temp2];
// 2.讀取時間
NSDate *temp3 = [NSDate date];
id object = [LXKArchiverTool unarchiverPath:filePath key:filePath];
[self endTimeLogStarDate:temp3];
NSDate *temp4 = [NSDate date];
YYCache *yyCache1 = [YYCache cacheWithName:filePath];
id value = [yyCache1 objectForKey:filePath];
[self endTimeLogStarDate:temp4];
// 3.刪除時間
NSDate *temp5 = [NSDate date];
[LXKArchiverTool removeArchiverObjectFilePath:filePath];
[self endTimeLogStarDate:temp5];
NSDate *temp6 = [NSDate date];
YYCache *yyCache2 = [YYCache cacheWithName:filePath];
[yyCache2 removeObjectForKey:filePath];
[self endTimeLogStarDate:temp6];
// 在此可以斷點(diǎn)是否刪除失敗 不用使用原來的對象去打印
id object1 = [LXKArchiverTool unarchiverPath:@"responseObject" key:@"responseObject"];
id value1 = [yyCache objectForKey:@"responseObject"];
}
- (void)endTimeLogStarDate:(NSDate *)startDete {
double dealTime = [[NSDate date] timeIntervalSinceDate:startDete];
// 使用毫秒測試 1s = 1000ms
NSLog(@"endTime === %f ms", dealTime * 1000);
}
@end
- 100個鍵值對字典對象測試數(shù)據(jù):
- 依次是歸檔時間,YYCache存儲時間
- 解歸檔時間,YYCache讀取時間
- 文件管理刪除時間,YYCache刪除時間
100個鍵值對對象測試數(shù)據(jù)
- 1000個鍵值對字典對象測試數(shù)據(jù):
1000個鍵值對字典對象測試數(shù)據(jù)
- 10000個鍵值對字典對象測試數(shù)據(jù):
10000個鍵值對字典對象測試數(shù)據(jù)
分析:
很明顯YYCache是要優(yōu)于歸檔的,階段差距在毫秒上還是挺大的,但是也沒有我想象中那么恐怖,還是可以用。
YYCache每一次都重新創(chuàng)建了對象,是因?yàn)闅w檔和解歸檔也是獨(dú)立的,如果不每一次都創(chuàng)建對象,其實(shí)YYCache的讀取和刪除都比解歸檔和文件刪除快的栋操。
能想到的比較是這樣的,YYCache是用了更對的代碼實(shí)現(xiàn)來換區(qū)時間上的優(yōu)勢,不過人家調(diào)用也非常好使,不過得出結(jié)論是歸檔和解歸檔還是可以用的闸餐。