【问题标题】:NSFetchedResultsController with NSPredicate in Two Different UIViewControllers - NSRangeExceptionNSFetchedResultsController 与 NSPredicate 在两个不同的 UIViewControllers - NSRangeException
【发布时间】:2012-08-09 06:11:40
【问题描述】:

我有两个不同的视图,由两个不同的视图控制器控制。每个视图里面都有一个 UITableView。每个 UITableView 都连接到一个 NSFetchedResultsController。在视图 1 中,我不想缩小我的 FRC 结果,所以我不使用谓词。在视图 2 中,我使用谓词来获取基于 BOOL(又名 NSNumber!)值的某些对象。但是当我尝试使用这个谓词时,当我转到视图 2 时,我得到一个 NSRangeException(超出范围的索引 1)。当我切换谓词时它也会抛出该异常(视图 1 上的谓词,视图 2 上没有谓词)。当我继续查看视图 2 时,再次出现异常。在某些情况下它是成功的(这两种情况都不是我想要的):

1) 我没有对任何一个获取请求使用任何谓词。

2) 我对视图 1 和视图 2 的获取请求使用相同的谓词。

一些代码供您欣赏:

在 View1.m 中:

-(NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
    return _fetchedResultsController;
}
NSManagedObjectContext *context = [CoreDataHelper getContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
                               entityForName:@"EditableSong" inManagedObjectContext:context];
[fetchRequest setEntity:entity];

NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                          initWithKey:@"dateModified" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:5];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:context sectionNameKeyPath:nil
                                               cacheName:@"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;

return _fetchedResultsController;

}

在 View2.m 中

-(NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
    return _fetchedResultsController;
}
NSManagedObjectContext *context = [CoreDataHelper getContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
                               entityForName:@"EditableSong" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                          initWithKey:@"dateModified" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"collaborative == %@", [NSNumber numberWithInt:0]];
[fetchRequest setPredicate:myPredicate];
[fetchRequest setFetchBatchSize:5];

NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:context sectionNameKeyPath:nil
                                               cacheName:@"Root"];
NSLog(@"here");
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;

}

这就是绿色错误箭头 (SIGABRT) 所指的地方(顺便说一下,这段代码在 View1 和 View2 中是一样的):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *MyIdentifier = [NSString stringWithFormat:@"MyIdentifier %i", indexPath.row];
SongTableViewCell *cell = (SongTableViewCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
    EditableSong *song = [_fetchedResultsController objectAtIndexPath:indexPath];//<<<------HERE!!! SIGABRT
    song.audioPlayer = [[AudioPlayer alloc] initWithSong:song];
    cell = [[SongTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier editableSong:song andVC:self];
    UIButton *playButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [playButton setBackgroundColor:[UIColor clearColor]];
    [playButton setImage:[UIImage imageNamed:@"mainmenuplay.png"] forState:UIControlStateNormal];
    playButton.frame = CGRectMake(300.0f, 15.0f, 65.0f, 65.0f);
    [playButton addTarget:self action:@selector(playSong:) forControlEvents:UIControlEventTouchUpInside];
    [cell.contentView addSubview:playButton];
}
return cell;

}

谢谢!

更新 1

这是我的 numberOfRowsInSection 方法(同样,两个类都一样):

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id  sectionInfo =
[[_fetchedResultsController sections] objectAtIndex:section];
NSLog(@"%i", [sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];

}

作为参考,该日志应该在 View1 中打印 3,在 View2 中打印 1,但两者都打印 3。

【问题讨论】:

  • 由于您得到NSRangeException (index 1 beyond bounds),这很可能意味着崩溃的NSFetchedResultsController 中的“数组”没有您要访问的数据。我建议验证您的表格视图部分/行是否与NSFetchedResultsController 中可用的数据正确对应。
  • 你为什么没有正确地排队你的单元格?如果它们看起来都一样,你应该给它们相同的标识符。 /(将初始化程序更改为通用的。)此外,您应该将单元格创建代码与单元格自定义代码分开(在 cellForRowAtIndexPath: 内。
  • 我将单元格标识符更改为您所说的通用名称。您能否通过将单元格创建与单元格自定义分开来进一步解释您的意思?我还能在哪里为引用当前类中的方法的单元格创建一个按钮?

标签: ios core-data uiviewcontroller nspredicate nsfetchedresultscontroller


【解决方案1】:

您返回的单元格数量似乎有误。 cellForRowAtIndexPath: 想创建一个单元格,但是没有objectAtIndexPath

所以你需要检查你的numberOfRowsInSection 方法。

【讨论】:

  • 感谢您最初的帮助 Mundi。但你能告诉我更多吗?我添加了一些关于我的numberOfRowsInSection 方法的信息。谢谢!
  • 应该是id &lt;NSFetchedResultsSectionInfo&gt; info
  • 嗯嗯。那没有用。如果我理解正确,我将代码更改为:id &lt;NSFetchedResultsSectionInfo&gt; sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
【解决方案2】:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    相关资源
    最近更新 更多