NSFetchedResultsController索引超出边界

时间:2010-07-03 03:07:16

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

我正在使用NSFetchedResultsController在我的表视图中显示项目:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return [[self.fetchedResultsController fetchedObjects] count];
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"TagCell";

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

 Tag *tag = [self.fetchedResultsController objectAtIndexPath:indexPath];
 cell.textLabel.text = tag.name;

    return cell;
}

但是,此代码在此行中断:

Tag *tag = [self.fetchedResultsController objectAtIndexPath:indexPath];

有了这条消息:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'

我已经NSLogged [self.fetchedResultsController fetchedObjects],我可以确认确实有Tag对象。如果我用这个替换上面的那一行,一切都按预期工作:

Tag *tag = [[self.fetchedResultsController fetchedObjects] objectAtIndex:indexPath.row];

我NSLogged indexPath并且索引是{0,0}(第0行0)所以我知道这不是该部分的问题。我非常困惑为什么会发生这种情况,因为从理论上讲,这两段代码做同样的事情。任何帮助表示赞赏。

由于

更新

id section = [[[self fetchedResultsController] sections] objectAtIndex:[indexPath section]];
NSLog(@"Section %@", section); <-- returns a valid section

此代码会导致相同的异常:Tag *tag = [[section objects] objectAtIndex:[indexPath row];

如果我NSLog [section objects]它返回一个空数组。我不确定为什么[fetchedResultsController fetchedObjects]返回带有正确对象的数组,[section objects]不返回任何内容。这是否意味着我正在创建的对象没有部分?这是我用来添加新对象的代码:

- (void)newTagWithName:(NSString *)name
{
    NSIndexPath *currentSelection = [self.tableView indexPathForSelectedRow];
    if (currentSelection != nil) {
        [self.tableView deselectRowAtIndexPath:currentSelection animated:NO];
    }    

    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
    Tag *newTag = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:self.managedObjectContext];

    // Configure new tag

    newTag.name = name;

    [self saveContext];

    NSIndexPath *rowPath = [self.fetchedResultsController indexPathForObject:newTag];
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:rowPath] withRowAnimation:UITableViewRowAnimationTop];
    [self.tableView selectRowAtIndexPath:rowPath animated:YES scrollPosition:UITableViewScrollPositionTop];
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}

这是我的saveContext方法:

- (void)saveContext
{
    // Save changes

    NSError *error;
    BOOL success = [self.managedObjectContext save:&error];
    if (!success)
    {
        UIAlertView *errorAlert = [[[UIAlertView alloc] initWithTitle:@"Error encountered while saving." message:nil delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil] autorelease];
        [errorAlert show];
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    }
}

我在这里做错了吗?

4 个答案:

答案 0 :(得分:17)

我遇到了同样的问题。在我的情况下,它似乎是一个损坏的缓存文件。尝试重命名缓存,或致电deleteCacheWithName:

答案 1 :(得分:6)

初始化获取请求控制器时,即使您的数据没有部分,也会为其指定sectionNameKeyPath:。然后,您将表格部分编号硬编码为1.

获取请求控制器正在尝试在没有任何部分的数据结构中返回部分索引为零的对象。

我通过将sectionNameKeyPath从nil更改为实体唯一属性的名称,在默认导航模板应用中重现了您的错误。

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"timeStamp" cacheName:@"Root"];

...然后改变了

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//    return [[fetchedResultsController sections] count];
     return 1;
}

我得到了:

 *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (0) beyond bounds (0)'

设置sectionNameKeyPath:nil,这应该可以解决您的问题。

答案 2 :(得分:1)

您是否正在编译,定位或测试3.0?

您从以下代码中获得了什么:

id section = [[[self fetchedResultsController] sections] objectAtIndex:[indexPath section]];
NSLog(@"Section %@", section);

您是否收到有效的部分?

如果是这样,请尝试添加以下行:

Tag *tag = [[section objects] objectAtIndex:[indexPath row];

如果这会产生错误,那么我怀疑问题出在您的-tableView: numberOfRowsInSection:中,并且可能会向UITableView提供错误的行数。你能编辑你的问题并发布该方法的代码吗?

更新

在进一步审查中,我看到TechZen指向的位置。你告诉表格视图你有一个部分,当你可能没有。进一步说,当你应该更简洁地回答它时,你会告诉它整个NSFetchedResultsController有多少个物体。

以下是对代码的轻微更改。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{
  return [[self fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
  return [[[self fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}

进行这些更改并查看其产生的影响。

问题

您实施了哪些其他UITableViewDataSource方法?听起来你的实现中至少还有一个挥之不去的错误。

答案 3 :(得分:1)

昨晚得到了这个错误,它让我发疯了。我发现如果您使用故事板来指定行数和节数,则需要匹配您在数据源方法中指定的数字。要完全修复错误,可以在属性检查器中将所有内容设置为0,然后以编程方式完成所有操作,或者只是确保数据源方法和属性检查器都反映相同数量的行和部分。

^^

相关问题