Core Data 不保存对象而且速度很慢
Posted
技术标签:
【中文标题】Core Data 不保存对象而且速度很慢【英文标题】:Core Data doesn't save objects and is slow 【发布时间】:2011-12-23 20:40:18 【问题描述】:我是第一次使用 Core Data,以斯坦福 ios 应用程序开发课程为指导。我几乎从演示应用程序中复制了代码(当然我根据自己的需要对其进行了调整),但目前我遇到了两个问题。
我的应用程序是一个地图视图,点击一个按钮就会显示一个模态视图控制器。此模式视图检查是否创建了 UIManagedDocument
。如果没有,它会创建一个并插入数据。此数据来自属性列表(258 项,所以没有太多)。如果它已经创建(通过先前显示该视图),如果我的逻辑成立,那么假设它也有内容应该是安全的,因为NSManagedObject
s 是在创建文档的同时创建的。第一次运行完美无缺,表格加载完毕,我的所有数据都正确显示。
但是,当我关闭然后重新显示我的模态视图时,表格保持为空。我正在检查文档的状态,即UIDocumentStateNormal
,所以查询它应该没问题。但事实并非如此:我的 fetchedResultsController 返回 0 行。如果我正确理解UIManagedContext
,我遇到的行为可能是由错误/不同的上下文引起的,但我确保:1) 我将我的文档(不仅仅是上下文)传递给prepareForSegue:sender
中的模态视图, 和 2) 当模态视图被解除时,我将带有上下文的文档传递回呈现视图。这就是为什么我认为这可能不是上下文,而是其他东西。
另一件事:在应用程序首次启动时插入 258 条记录在模拟器中已经足够快了。但是,在我的手机上,这可能需要整整 13 秒。插入代码如下所示(为便于阅读而修改):
+ (Department *)departmentName:(NSString *)name
withAttributes:(NSDictionary *)attributes
inContext:(NSManagedObjectContext *)context
Department *department = [NSEntityDescription insertNewObjectForEntityForName:@"Department" inManagedObjectContext:context];
department.name = name;
NSArray *informationElements = [attributes objectForKey:@"information"];
for (int i = 0; i < [informationElements count]; i++)
NSString *informationValue = [[informationElements objectAtIndex:i] objectForKey:@"value"];
if ([[[informationElements objectAtIndex:i] objectForKey:@"description"] isEqualToString:@"phone"])
department.phone = informationValue;
else if ([[[informationElements objectAtIndex:i] objectForKey:@"description"] isEqualToString:@"email"])
department.email = informationValue;
else if ([[[informationElements objectAtIndex:i] objectForKey:@"description"] isEqualToString:@"web"])
department.website = informationValue;
return department;
明确一点:这段代码工作得很好,但它真的很慢。它被封装在一个被精确调用 258 次的方法中。 informationElements
最多包含三个元素,这意味着最多有 258 * 3 = 774 个循环。实际上比这要少得多,但即使是 774,也不应该需要 13 秒,对吧?
下面的sn-p显示UIManagedDocument
的初始化:
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.database.fileURL path]])
[self.database saveToURL:self.database.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
[self setupFetchedResultsController];
[self fetchDepartmentsIntoDocument:self.database];
];
else if (self.database.documentState == UIDocumentStateClosed)
[self.database openWithCompletionHandler:^(BOOL success)
[self setupFetchedResultsController];
];
else if (self.database.documentState == UIDocumentStateNormal)
[self setupFetchedResultsController];
fetchDepartmentsIntoDocument
读取属性列表,然后运行一个循环,为每个属性列表项调用departmentName:withAttributes:inContext
。
如果有人能给我一些帮助,将不胜感激!
【问题讨论】:
你在不同的线程上试过了吗? 我没有。是否有可能是数据过多而无法足够快地处理? 可能是,我使用核心数据来保存我的单例对象,它工作正常,但你的看起来确实要复杂得多。我说它是一种对有效但缓慢的东西的笼统声明。除非有理由怀疑。 好的,我已将循环限制为仅执行 15 个项目,而且运行速度要快得多,因此我将尝试在线程中运行它。但是,我的数据没有被保存的问题仍然存在。 【参考方案1】:对于速度问题,我会考虑使用谓词;这应该会大大加快速度!
谓词使上下文仅根据您选择的任何标准返回所需的值。它们更快的原因是它不必将每个存储的实体对象转换为托管对象,而是可以直接从属性中提取,从而大大加快了比较速度。
【讨论】:
是的,这将是一个选项,除了我真的需要所有这些对象。这是一个表格,显示了用户可以从中选择一个的所有部门。如果真的没有办法解决速度问题,我将不得不改变它,但现在我想看看是否还有其他方法可以让我当前的 UI 保持低于一秒的速度。跨度> 【参考方案2】:当您将 Department 对象插入上下文时,您是否为每个对象保存?插入相对便宜,但保存(即-[NSManagedobjectContext save:]
)代价高昂(因为数据库必须进行锁定和文件 I/O)。
另外,在风格上,你可以这样做
for (NSDictionary *element in informationElements)
NSString *informationValue = [element objectForKey:@"value"];
if ([[element objectForKey:@"description"] isEqualToString:@"phone"])
department.phone = informationValue;
else if ([[element objectForKey:@"description"] isEqualToString:@"email"])
department.email = informationValue;
else if ([[element objectForKey:@"description"] isEqualToString:@"web"])
department.website = informationValue;
遍历您的字典数组。
【讨论】:
我实际上依赖于 UIDocument 的自动保存机制,所以我根本没有保存。即使手动保存,我的数据也不会在视图切换之间存储。我也知道快速枚举,但由于我目前的方法也用于讲座,我想我就用那个。以上是关于Core Data 不保存对象而且速度很慢的主要内容,如果未能解决你的问题,请参考以下文章
如何在 RestKit 中保存到 Core Data RKMappingResult 对象?