快速NSData取消归档

时间:2018-04-09 11:29:31

标签: ios objective-c nsdata

我从类实例创建NSData

NSData* data = [NSKeyedArchiver archivedDataWithRootObject:db];
[data writeToFile:@"/Users/.../db.data" atomically:true];

然后我需要加载这个实例:

NSURL* dbUrl = [[NSBundle mainBundle]URLForResource:@"db" withExtension:@"data"];
NSData* dbData = [NSData dataWithContentsOfURL:dbUrl];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    self.db = [NSKeyedUnarchiver unarchiveObjectWithData:dbData];
});

此加载持续cca。 ~70MB文件大小为6秒。这很慢!我试图将db实例分成两个不同的部分(~35MB)并加载它们:

self.db = [[Database alloc]init];
NSURL* dbUrl1 = [[NSBundle mainBundle]URLForResource:@"db1" withExtension:@"data"];
NSData* dbData1 = [NSData dataWithContentsOfURL:dbUrl1];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    self.db.nodes = [NSKeyedUnarchiver unarchiveObjectWithData:dbData1];
});
NSURL* dbUrl2 = [[NSBundle mainBundle]URLForResource:@"db2" withExtension:@"data"];
NSData* dbData2 = [NSData dataWithContentsOfURL:dbUrl2];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    self.db.trips = [NSKeyedUnarchiver unarchiveObjectWithData:dbData2];
});

通过这种方式加载持续cca。 3秒(快2倍)。你知道另一种加载方式吗?

编辑1:

我不确定它可以提供帮助,但归档对象有两个NSMutableArray个实例。第一个包含很多Node个对象:

@interface DatabaseNode : NSObject <NSCoding>

@property (assign, nonatomic) NSInteger index;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) double lat;
@property (assign, nonatomic) double lon;

@end

第二个包含很多Trip个对象:

@interface DatabaseTrip : NSObject <NSCoding>

@property (assign, nonatomic) NSInteger index;
@property (strong, nonatomic) NSString* name;
@property (assign, nonatomic) NSInteger service;
@property (strong, nonatomic) NSMutableArray* departureTimes; //Contains NSDate

@end

1 个答案:

答案 0 :(得分:1)

鉴于您需要从应用程序会话开始时内存中的所有数据,您将不得不使用NSKeyedArchiver以外的解决方案。 NSKA旨在存档复杂的对象图,因此经过优化可以解决不同的问题。

在你的情况下,我建议一个构建阶段,它将静态数据写入一个文件格式,可以在不解析的情况下映射到内存中。然后,在运行时,映射文件并有一个传递,将其转换为基础类型中的最小封装。

对于字符串,像解决方案这样的字符串表将运行良好。日期可能有点棘手。我测试看基于时间间隔的创建方法是否很快。如果是,那么您可以在映射文件中将日期存储为数组(不是NSArrays,而是NSTimeIntervals的平面C数组)并执行修正传递。

当然,您也可以根据应用中的访问模式跳过某些数据子集的修正。如果您的用户没有真正同时查看所有日期,则无需在加载时修复它们,但可以按需创建它们。