【问题标题】:Core Data Error: Execute Fetch Request Error - Crashes when trying to access Core Data核心数据错误:执行获取请求错误 - 尝试访问核心数据时崩溃
【发布时间】:2013-08-04 17:22:03
【问题描述】:

我正在为我的 iOS 项目使用 Core Data,并且在运行应用程序。我的应用确实有一个实体,但不确定为什么此错误仍然存​​在。

这是文件中出现错误的核心数据代码:

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];

    return [sectionInfo numberOfObjects];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"ClassesCell";

    ClassTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[ClassTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

- (void)configureCell:(ClassTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    Classes *classID = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.classLabel.text = classID.classTitle;
    cell.periodLabel.text = classID.period;
}

#pragma mark - Fetched results controller

- (NSFetchedResultsController *)fetchedResultsController
{
    if (_fetchedResultsController != nil) {
        return _fetchedResultsController;
    }


    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyClassesID" inManagedObjectContext:self.managedObjectContext];
    assert(self.managedObjectContext);

    [fetchRequest setEntity:entity];

    [fetchRequest setFetchBatchSize:20];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"period" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
   [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;

    if (![self.fetchedResultsController performFetch:&error]) {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _fetchedResultsController;


}

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
                    atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

【问题讨论】:

  • 代码运行时是设置了managedObjectContext还是nil
  • @Wain 我不太确定。这是我第一次在 iOS 上编码。我在哪里可以找到?
  • 在您创建获取请求的行上放置一个断点并调试以检查是否设置了引用。
  • @Wain 我按照你的建议做了,结果发现 managedObjectContext 是 nil

标签: iphone ios xcode macos


【解决方案1】:

您需要确保已设置托管对象上下文引用。如果未设置,则获取请求将无法定位实体。


您必须在某处拥有一个类,该类是托管对象上下文的所有者。默认情况下(来自 Apple 提供的模板)这是应用程序委托。当应用程序委托创建控制器类时,它应该向控制器传递对 MOC 的引用。如果应用代理没有创建控制器,那么控制器可以去应用代理获取引用。

【讨论】:

  • 如何设置参考?
  • 我为获取请求生成了相同的异常,并且我检查了我的 MOC 不为零。我该怎么办?
【解决方案2】:

第一: 在创建数据模型时,最好避免使用任何 NSObject 保留词,例如“Class”。我刚刚在 Xcode 4.6.3 中尝试使用名称“class”作为属性,Data Modeller 告诉我“class”是 NSObject 中的保留名称。自我、实体、描述或其他等词也是如此。

第二次: 此外,可能发生的情况是您最初创建了数据模型,运行了 Core Data 应用程序来测试它,然后修改了 Core Data 模型,现在您尝试再次针对旧的 sqlite 数据库运行应用程序。要解决此问题,您可以删除模拟器使用的目录中的 SQLite 数据库,然后再次运行您的应用程序。注意:仅在您进行初始开发时执行此操作,而不是在您发布应用程序之后执行此操作。应用发布后,使用核心数据模型版本控制和数据迁移。

说明:

启动终端控制台

要找到它的位置,首先进入 iPhone 模拟器目录,如下所示:

cd ~/Library/Application\ Support/iPhone\ Simulator/

然后根据您正在测试的 iOS 版本(我的是 6.1)更改下面适合您的行:

cd 6.1/应用程序

模拟器创建的目录名称看起来很神秘。您的可能是最后一个,或者如果您在模拟不同项目之间返回和第四个,它可能是倒数第二个,倒数第三个等。首先尝试最后一个。我的是:F53A66CD-DB9A-4440-9178-28BCF4A7A571 因此我做了以下事情:

cd F53A66CD-DB9A-4440-9178-28BCF4A7A571

然后输入:

cd 文档

然后输入以下命令列出文件:

ls

您应该会看到列出的 .sqlite 文件。 说你的是 myClasses.sqlite

要删除它,请键入以下内容:

rm myClasses.sqlite

然后构建并运行以再次测试您的应用程序。

Dougpan.com

【讨论】:

  • 我试过了,文件名为 HomeworkApp.sqlite,我删除了它。再次运行应用程序后,同样的错误仍然存​​在
  • 您是否尝试过使用核心数据模型版本控制和数据迁移?哈希用于比较对数据模型的任何修改与代码中的内容。另请记住,如果您选择了一个属性并选择了编辑、创建 NSManagedObject 子类,那么您的代码可能正在使用一个类。您可能还需要更新它,并查看并更新使用这些类的代码。
  • 尝试放置一些调试代码来测试您的获取请求,例如: NSArray *fetch = [itemController.managedObjectContext executeFetchRequest:fetchRequest error:&error]; NSLog(@"%d",fetch.count);
猜你喜欢
  • 2019-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 2017-10-13
  • 1970-01-01
相关资源
最近更新 更多