NSFetchedResultsController objectAtIndex、objectAtIndexPath、indexPathForObject 不一致
我有一个包含单个部分的提取结果。我可以使用 [[fetchedResultsController fetchedObjects] objectAtIndex:index]
访问所有对象的对象。但是,当我像这样使用 objectAtIndexPath 时,它会失败: [fetchedResultsController objectAtIndexpath:indexPath]
将一行(对于其中一个 SearchResult 对象)插入到相应的表中后发生错误。该对象似乎已正确插入到新表中。在我目视确认这一点后,我选择其中一行,然后乐趣就开始了。
这是发生错误的代码:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SearchResult *event;
NSLog(@"Number of sections in fetchedResultsController: %d", [[fetchedResultsController sections] count]);
for (NSUInteger i=0; i<[[fetchedResultsController fetchedObjects] count]; i++) {
event = (SearchResult*)[[fetchedResultsController fetchedObjects] objectAtIndex:i];
NSLog(@"object at index[%d]: %@", i, event.title );
NSLog(@"indexPath for object at index[%d]:%@", i, [fetchedResultsController indexPathForObject:event]);
}
NSLog(@"indexPath passed to method: %@", indexPath);
SearchResult *result = [fetchedResultsController objectAtIndexPath:indexPath]; // *** here is where the error occurs ***
[viewDelegate getDetails:result];
}
我在最后一行出现故障。日志如下所示:
Number of sections in fetchedResultsController: 1
object at index[0]: Cirles
indexPath for object at index[0]:(null)
object at index[1]: Begin
indexPath for object at index[1]:(null)
object at index[2]: Copy
indexPath for object at index[2]:(null)
object at index[3]: Unbound
indexPath for object at index[3]:(null)
indexPath passed to method: <NSIndexPath 0x64ddea0> 2 indexes [0, 2]
执行 NSLog 语句后,我使用 [fetchedResultsController objectAtIndexPath:indexPath]
在最后一行收到异常。其他索引值也会发生这种情况,但它们看起来总是有效的。
*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“索引 0 部分中索引 2 处没有对象”
因此,总而言之,似乎存在正确数量的获取对象,有一个部分(0),我可以通过一种方法访问每个部分,但不能通过另一种方法访问。 indexPathForObject: 始终返回 (null)。
这是一个错误还是我误解了什么?
更新
这是实现 NSFetchedResultsControllerDelegate 协议方法的代码。
- (void) controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"Favorites controllerWillChangeContent");
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
NSLog(@"Favorites Table controllerDidChangeContent");
[self.tableView endUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"Favorites Changed Object");
switch (type) {
case NSFetchedResultsChangeInsert:
NSLog(@"--- Favorite was inserted");
if ([[self.fetchedResultsController fetchedObjects] count] == 1) {
// configure first cell to replace the empty list indicator by first deleting the "empty" row
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeDelete:
NSLog(@"--- Favorite was deleted");
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
if ([[self.fetchedResultsController fetchedObjects] count] == 0) {
// configure first cell to show that we have an empty list
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
break;
case NSFetchedResultsChangeMove:
NSLog(@"--- Favorite was moved");
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"--- Favorite was updated");
[self configureCell:(ResultCell*)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
default:
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type {
switch (type) {
case NSFetchedResultsChangeInsert:
NSLog(@"Favorites Section Added");
break;
case NSFetchedResultsChangeDelete:
NSLog(@"Favorites Section Deleted");
break;
default:
break;
}
}
更新 2
我不知道这是否重要,但 tableView 是用这一行初始化的:
tableView = [[UITableView alloc] initWithFrame:CGRectMake(...) style:UITableViewStyleGrouped];
更新 3
当我按如下方式更改有问题的行时,它工作正常。但我宁愿保持索引与表相同。
//SearchResult *result = [self.fetchedResultsController objectAtIndexPath:indexPath];
SearchResult *result = [[self.fetchedResultsController fetchedObjects] objectAtIndex:[indexPath indexAtPosition:1]]
I have a fetched result with a single section. I am able to access the objects using [[fetchedResultsController fetchedObjects] objectAtIndex:index]
for all of the objects. But it is failing when I use objectAtIndexPath like this: [fetchedResultsController objectAtIndexpath:indexPath]
An error occurs after I insert an row (for one of the SearchResult objects) into the corresponding table. The object appears to be inserted into the new table correctly. After I have visually confirmed this, I select one of the rows, and then the fun begins.
Here is the code where the error is occurring:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SearchResult *event;
NSLog(@"Number of sections in fetchedResultsController: %d", [[fetchedResultsController sections] count]);
for (NSUInteger i=0; i<[[fetchedResultsController fetchedObjects] count]; i++) {
event = (SearchResult*)[[fetchedResultsController fetchedObjects] objectAtIndex:i];
NSLog(@"object at index[%d]: %@", i, event.title );
NSLog(@"indexPath for object at index[%d]:%@", i, [fetchedResultsController indexPathForObject:event]);
}
NSLog(@"indexPath passed to method: %@", indexPath);
SearchResult *result = [fetchedResultsController objectAtIndexPath:indexPath]; // *** here is where the error occurs ***
[viewDelegate getDetails:result];
}
I am having a failure in the last line. The log looks like this:
Number of sections in fetchedResultsController: 1
object at index[0]: Cirles
indexPath for object at index[0]:(null)
object at index[1]: Begin
indexPath for object at index[1]:(null)
object at index[2]: Copy
indexPath for object at index[2]:(null)
object at index[3]: Unbound
indexPath for object at index[3]:(null)
indexPath passed to method: <NSIndexPath 0x64ddea0> 2 indexes [0, 2]
After executing the NSLog statements, I get an exception at the last line using [fetchedResultsController objectAtIndexPath:indexPath]
. It happens for other index values too, but they always look valid.
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no object at index 2 in section at index 0'
So, to summarize, there appear to be the right number of fetched objects, there is one section (0), I can access each one by one method, but not by the other. The indexPathForObject: is always returning (null).
Is this a bug or am I misunderstanding something?
UPDATE
Here is the code, implementing the NSFetchedResultsControllerDelegate protocol methods.
- (void) controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"Favorites controllerWillChangeContent");
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
NSLog(@"Favorites Table controllerDidChangeContent");
[self.tableView endUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"Favorites Changed Object");
switch (type) {
case NSFetchedResultsChangeInsert:
NSLog(@"--- Favorite was inserted");
if ([[self.fetchedResultsController fetchedObjects] count] == 1) {
// configure first cell to replace the empty list indicator by first deleting the "empty" row
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
}
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeDelete:
NSLog(@"--- Favorite was deleted");
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
if ([[self.fetchedResultsController fetchedObjects] count] == 0) {
// configure first cell to show that we have an empty list
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
break;
case NSFetchedResultsChangeMove:
NSLog(@"--- Favorite was moved");
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"--- Favorite was updated");
[self configureCell:(ResultCell*)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
default:
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type {
switch (type) {
case NSFetchedResultsChangeInsert:
NSLog(@"Favorites Section Added");
break;
case NSFetchedResultsChangeDelete:
NSLog(@"Favorites Section Deleted");
break;
default:
break;
}
}
UPDATE 2
I don't know if it matters, but the tableView is initialized with this line:
tableView = [[UITableView alloc] initWithFrame:CGRectMake(...) style:UITableViewStyleGrouped];
UPDATE 3
When I change the offending line as follows, it works fine. But I would rather keep the indexing the same as it is with the table.
//SearchResult *result = [self.fetchedResultsController objectAtIndexPath:indexPath];
SearchResult *result = [[self.fetchedResultsController fetchedObjects] objectAtIndex:[indexPath indexAtPosition:1]]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我现在也有同样的问题。
对我来说,它有助于使用
cacheName: nil
初始化NSFetchedResultsController
。I had the same problem now.
For me it helped to initialise
NSFetchedResultsController
withcacheName: nil
.