核心数据。 NSDictionary VS NSFetchRequest?

时间:2013-10-05 09:53:01

标签: ios core-data nsdictionary nsmutabledictionary nsfetchrequest

我有一些数据包括2个表的记录:对和项目。这些表与多对多关系相关联。我看到有两种方法可以填充核心数据实体。让我们已经填写了所有项目,现在我们应该填写对。在这两种情况下,“标识符”是一个额外的文本属性/字段。

方式1(仅限NSFetchRequest):

//get data which should be converted to core data entities
id pairsInfoArray = ...; 
for (id pairInfo in pairsInfoArray) {

    //get items by identifier using NSFetchRequest
    id item1 = ...;
    id item2 = ...;
    //create pair entity
    id pair = ...;
    pair.items = [NSSet setWithObjects:item1, item2, nil];
}

方式2(仅调用一次NSFetchRequest并改为使用NSDictionary / NSMutableDictionary):

//get all items via NSFetchRequest
NSArray *itemsObjArray = ...;
//place all the items into array as key = item.identifier, value = item (as object)
NSMutableDictionary *itemsObjDict = ...;
//get data which should be converted to core data entities
id pairsInfoArray = ...;
for (id pairInfo in pairsInfoArray) {

    //get items by key from itemsObjDict
    id item1 = ...;
    id item2 = ...;
    //create pair entity
    id pair = ...;
    pair.items = [NSSet setWithObjects:item1, item2, nil];
}

我的所有数据(不仅是项目和对)都在5分钟(way1)和45秒(way2)期间填充。它包括执行[context save:nil]的时间。

我认为第二种方式比第一种方式更快。但它有任何隐藏的缺点吗​​?例如,不将项目保存到附加字典会浪费内存吗?

2 个答案:

答案 0 :(得分:1)

你没有表明你如何保存 - 这可能会产生相当大的影响。

选项1具有内存效率,但不具备时间效率。

选项2是节省时间但不是内存效率(你试过通过仪器/在旧设备上运行吗?)。

您应该考虑运行(并保存)批次的混合解决方案。通过试验和分析设置批量大小。 Instruments提供了许多核心数据工具来帮助解决这个问题。您的目标是尽可能减少内存使用量,最小提取次数和最小上下文保存次数。

答案 1 :(得分:1)

当然有一个很大的劣势。

您在示例2中将所有数据保存在内存中。当然,这始终是最快的方式,但对移动设备而言并非最佳。

CoreData是一个对象图,而不是一个存储库。默认情况下,它不会使用内存来立即创建对象。它在您实际开始使用它时创建对象,意味着使用属性。在它之前只有一个小参考 - 所谓的故障。 CoreData可以平衡内存与性能的关系,并允许您控制加载到内存中的数据以及何时加载。从获取中获得的NSArray实际上只有很少的对象准备好在内存中。当您访问元素时,其余部分变为真实。当我们一直需要所有对象时,我们通常没有任何情况。通常我们的Collectionviews只显示一些对象的一些信息,但绝不是全部。当然,您可以简单地获取所有对象并告诉他实际加载对象。然后他将和第二个例子一样快。在某些情况下可能更快,因为当涉及到交叉等时,NSSet具有一些惊人的力量。

有一些很好的WWDC研讨会展示了如何处理这个问题。一般来说,CoreData始终是最好的解决方案,除非我们谈论只需要花费几kb的内存并且保持它们不会造成任何伤害的琐碎数据。但你的时间数字告诉你有很多数据。并非此数据中的所有内容都是必需的。拆分它,创建一个实体,其中包含您需要显示的必要信息,并将其余信息放在一个额外的实体中。当您需要详细信息时,您可以访问额外的实体,并且只需很短的延迟即可获得该对象。 (称为延迟加载)

在Core数据中尝试我的建议,看看你在设备上运行时使用了多少内存而不是NSDictionary解决方案。我想你会看到差异。