NSFetchedResultsController返回具有null indexPaths的对象

时间:2010-07-17 05:02:25

标签: iphone cocoa cocoa-touch core-data nsfetchedresultscontroller

详细信息在评论中。

以下代码:

// Perform the fetch...
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

// Confirm that objects were fetched by counting them...
NSLog(@"Number of Objects = %i",
      [[fetchedResultsController fetchedObjects] count]);

// Confirm that sections exist by counting them...
NSLog(@"Numbers of Sections = %i",
      [[fetchedResultsController sections] count]); 

for (id section in [fetchedResultsController sections]) {
    // Count number of objects in each section
    // _The fact that this outputs 0 is the first sign of trouble_
    NSLog(@"Number of Objects in Section = %i", [section numberOfObjects]);
}

for (Reminder *reminder in [fetchedResultsController fetchedObjects]) {
    // Confirm that the objects fetched are in fact real objects
    // by accessing their "textContent" property...
    NSLog(@"textContent=%@", reminder.textContent);

    // Show that the fetched objects are being returned 
    // with a (null) indexPath...
    // _The second sign of trouble..._
    NSLog(@"IndexPath=%@",
          [fetchedResultsController indexPathForObject:reminder]);
}

NSUInteger indexArr[] = {0,0};
NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexArr 
                                                    length:2];

// _Application crashes on this line because the fetched 
// objects do not have indexPaths_
Reminder *testReminder = (Reminder *)[fetchedResultsController 
                                      objectAtIndexPath:indexPath]; 
NSLog(@"textContent = %@", testReminder.textContent);

结果如下:

2010-07-17 00:48:41.865 Reminders[27335:207] Number of Objects = 3
2010-07-17 00:48:41.867 Reminders[27335:207] Numbers of Sections = 1
2010-07-17 00:48:41.868 Reminders[27335:207] Number of Objects in Section = 0
2010-07-17 00:48:41.870 Reminders[27335:207] textContent=Imported Object 3
2010-07-17 00:48:41.871 Reminders[27335:207] IndexPath=(null)
2010-07-17 00:48:41.873 Reminders[27335:207] textContent=Imported Object 2
2010-07-17 00:48:41.873 Reminders[27335:207] IndexPath=(null)
2010-07-17 00:48:41.874 Reminders[27335:207] textContent=Imported Object 1
2010-07-17 00:48:41.875 Reminders[27335:207] IndexPath=(null)
2010-07-17 00:48:41.887 Reminders[27335:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'

任何想法都将不胜感激。仅供参考,如果我使用不同的模板作为起点,上面的代码在单独的应用程序中完美运行。即如果我使用“基于窗口的应用程序”模板,代码将失败。如果我使用“基于导航的应用程序”,代码将按预期工作。

更新:TechZen想知道问题是否是由我的提醒实体引起的。我认为这是一个好主意,所以我做了以下几点:

  1. 创建两个默认模板应用程序:“基于窗口的应用程序”和“基于导航的应用程序”(均启用了Core Data)

  2. 复制从基于导航到基于Window的最小代码,以执行上述测试(几乎只是“xcdatamodel”文件,fetchedresultscontroller,以及添加测试对象的方法)。 / p>

  3. 上述代码仍然在新的“基于窗口的提醒实体”应用程序中失败。 (在这个新的测试应用程序中,实际上我自己编写了零代码(在测试代码之外),它只是模板代码被剪切和粘贴在一起。)

    现在,我正在寻找任何方式以在创建“基于窗口的应用程序”后运行上述代码。以下是使用基于导航的默认实体执行测试的代码,以防有人有兴趣尝试:

    UPDATE 请注意,正如TechZen所述,无论如何使用空数据库运行,此代码都会崩溃,因此如果从基于窗口的应用程序开始,首先将一些对象添加到数据库然后添加测试代码。

    // Confirm that objects were fetched
    NSLog(@"Number of Objects = %i",
          [[fetchedResultsController fetchedObjects] count]);
    
    // Confirm that sections exist
    NSLog(@"Numbers of Sections = %i",
          [[fetchedResultsController sections] count]); 
    
    for (id section in [fetchedResultsController sections]) {
    
        // Count number of objects in sections
        // _The fact that this outputs 0 is the first sign of trouble_
        NSLog(@"Number of Objects in Section = %i", [section numberOfObjects]);
    }
    
    for (NSManagedObject *managedObject in [fetchedResultsController fetchedObjects]) {
    
        // Confirm that the objects fetched are in fact real objects, 
        // by accessing their "timeStamp" property
        NSLog(@"TimeStamp=%@", [[managedObject valueForKey:@"timeStamp"] description]);
    
        // Show that the fetched objects are being returned 
        // with a (null) indexPath
        // _The second sign of trouble..._
        NSLog(@"IndexPath=%@",
              [fetchedResultsController indexPathForObject:managedObject]);
    }
    
    NSUInteger indexArr[] = {0,0};
    NSIndexPath *indexPath = [NSIndexPath indexPathWithIndexes:indexArr 
                                                        length:2];
    
    // _Application crashes on this line, because the fetched 
    // objects do not have indexPaths_
    NSManagedObject *managedObject = [fetchedResultsController 
                                      objectAtIndexPath:indexPath];
    NSLog(@"textContent = %@", [[managedObject valueForKey:@"timeStamp"] description]);
    

    UPDATE 这是使用新剪切代码时的输出

    2010-07-18 15:33:41.264 Reminders[30898:207] Number of Objects = 3
    2010-07-18 15:33:41.266 Reminders[30898:207] Numbers of Sections = 1
    2010-07-18 15:33:41.267 Reminders[30898:207] Number of Objects in Section = 0
    2010-07-18 15:33:41.270 Reminders[30898:207] TimeStamp=2010-07-18 13:59:00 -0400
    2010-07-18 15:33:41.271 Reminders[30898:207] IndexPath=(null)
    2010-07-18 15:33:41.272 Reminders[30898:207] TimeStamp=2010-07-18 13:59:00 -0400
    2010-07-18 15:33:41.273 Reminders[30898:207] IndexPath=(null)
    2010-07-18 15:33:41.274 Reminders[30898:207] TimeStamp=2010-07-18 13:58:59 -0400
    2010-07-18 15:33:41.275 Reminders[30898:207] IndexPath=(null)
    2010-07-18 15:33:41.276 Reminders[30898:207] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'
    

    更新所以我将此问题缩小为与SDK版本相关的问题,我现在有一个项目,如果我使用模拟器3.2构建它崩溃,并使用模拟器3.1.3构建它的工作原理精细。但是如果我添加一个UITableViewController,然后用Simulator 3.2构建,那么它再次正常工作。所以我创建了一个new stackoverflow帖子来提问:如果你在没有UITableViewController的情况下使用NSFetchedResultsController,你如何与对象进行交互? (因为IndexPaths不可靠)。

    更新通过使用 - [NSFetchedResultsController fetchedObjects] objectAtIndex:]来访问对象,暂时解决了这个问题。

6 个答案:

答案 0 :(得分:3)

这可以通过使用 - [NSFetchedResultsController fetchedObjects] objectAtIndex:]

来绕过

答案 1 :(得分:3)

您是否尝试在仅内存跟踪模式下使用NSFetchedResultsController? (仅内存跟踪:委托是非零的,文件缓存名称设置为nil)

答案 2 :(得分:2)

我想我很愚蠢地指出这一点 NSLog(@“%@”,indexPath)将始终返回null?

你需要做

NSLog(@"section %i",(int)indexPath.section);
NSLog(@"row %i",(int)indexPath.row);

不是吗?

答案 3 :(得分:1)

查看fetchedResultsController的sortDescriptors顺序。段键字段必须首先按顺序排序。

如果fetchedResultsController有多个sortDescriptor,并且第一个描述符不是section keyFor field而不是indexPathForObject:方法无法解析indexPath。

答案 4 :(得分:0)

NSFetchedResultsController的创建是什么样的?

更新

仅供参考,您可以使用代码更新您的问题,而不是使用PasteBin。

您是否在此代码中使用多个线程来访问NSFetchedResultsController

答案 5 :(得分:0)

我将您的代码复制并粘贴到默认的Core Data导航模板中,使用字符串属性textContent将实体更改为Reminder并且运行正常。此代码或获取的结果控制器的设置没有任何问题。

我认为问题实际上是您的Reminder实体,Reminder类或textContent属性或对象。这些错误可能是由于无法正确处理Reminder对象造成的。


编辑:

确保在将某些对象添加到上下文后才运行此测试。如果没有对象,它将崩溃。我将使用基于窗口的模板进行测试。