【发布时间】:2011-12-23 20:40:18
【问题描述】:
我是第一次使用 Core Data,以斯坦福 iOS 应用程序开发课程为指导。我几乎从演示应用程序中复制了代码(当然我根据自己的需要对其进行了调整),但目前我遇到了两个问题。
我的应用程序是一个地图视图,点击一个按钮就会显示一个模态视图控制器。此模式视图检查是否创建了 UIManagedDocument。如果没有,它会创建一个并插入数据。此数据来自属性列表(258 项,所以没有太多)。如果它已经创建(通过先前显示该视图),如果我的逻辑成立,那么假设它也有内容应该是安全的,因为NSManagedObjects 是在创建文档的同时创建的。第一次运行完美无缺,表格加载完毕,我的所有数据都正确显示。
但是,当我关闭然后重新显示我的模态视图时,表格保持为空。我正在检查文档的状态,即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 个项目,而且运行速度要快得多,因此我将尝试在线程中运行它。但是,我的数据没有被保存的问题仍然存在。