【问题标题】:Core Data doesn't save objects and is slowCore Data 不保存对象而且速度很慢
【发布时间】: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 个项目,而且运行速度要快得多,因此我将尝试在线程中运行它。但是,我的数据没有被保存的问题仍然存在。

标签: core-data ios5 xcode4.2


【解决方案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 的自动保存机制,所以我根本没有保存。即使手动保存,我的数据也不会在视图切换之间存储。我也知道快速枚举,但由于我目前的方法也用于讲座,我想我就用那个。
猜你喜欢
  • 2015-10-15
  • 2019-12-05
  • 2019-05-09
  • 1970-01-01
  • 2012-12-23
  • 2012-05-25
  • 1970-01-01
  • 2022-08-19
  • 2023-03-08
相关资源
最近更新 更多