我在这里有一个(至少对我来说)奇怪的问题:
我有一个 UITableViewController,它有一个 NSFetchedResultsController 来处理要显示的数据。
应该显示的数据来自服务器,为了使它更容易,可以说它是一种聊天。
一个简化的模型可以描述如下。
--------------- ----------------- -----------------
| MainTopic | | Thread | | Message |
--------------- ----------------- -----------------
| topicID (E) | | threadID (E) | | msgID (E) |
| name (E) | | name (E) | | msgText (E) |
--------------- ----------------- | msgDate (E) |
| threads (R) | <------>> | mainTopic (R) | -----------------
--------------- | messages (R) | <------>> | thread (R) |
----------------- -----------------
数据来自一个总是为 MainTopic 填充所有消息的服务器(这不在我手中)。
对于 CoreData,我有一个控制器,它被实现为单例。它有一个由 NSFetchedResultsController 使用的 mainContext (NSManagedObjectContext)。插入新数据是在单独的 NSManagedObjectContext 上完成的,它在保存时在 mainContext 上调用 mergeChangesFromContextDidSaveNotification:。
Thread 类有一个 compare:-Method,所以它也可以用于 sortdescriptor。
回到 UITableViewController:
在 viewDidLoad 上,它创建了 NSFetchedResultsController,它获取 topicID 的所有消息,sectionNameKeyPath 设置为“thread”并在 FetchedResultsController 上执行获取。
UITableView 还实现了 NSFetchedResultsControllerDelegate 以便在新消息到达时更新 TableView。这就是我的问题开始的地方。
从服务器重新获取后,表视图可能如下所示
______________________________________
| Thread: First thread |
|____________________________________|
|____________________________________|
| Message 1 |
| Message 2 |
|____________________________________|
| Thread: Second thread |
|____________________________________|
|____________________________________|
| Message 1 |
| Message 2 |
|____________________________________|
现在有人将消息(消息 3)写入第一个线程,从服务器获取数据(用户保留在表视图中)。现在表格视图看起来像这样
______________________________________
| Thread: First thread |
|____________________________________|
|____________________________________|
| Message 1 |
| Message 2 |
|____________________________________|
| Thread: First thread |
|____________________________________|
|____________________________________|
| Message 3 |
|____________________________________|
| Thread: Second thread |
|____________________________________|
|____________________________________|
| Message 1 |
| Message 2 |
|____________________________________|
如您所见,第一个线程的部分标题出现了两次。
如果 UITableViewController 将被留下并再次打开(弹出并将新实例推送到 navigationController),表格看起来很好:
______________________________________
| Thread: First thread |
|____________________________________|
|____________________________________|
| Message 1 |
| Message 2 |
| Message 3 |
|____________________________________|
| Thread: Second thread |
|____________________________________|
|____________________________________|
| Message 1 |
| Message 2 |
|____________________________________|
所以我认为错误必须在 NSFetchedResultsControllerDelegate 方法中的某个地方,但因为它们看起来“正常”。
#pragma mark - NSFetchedResultsControllerDelegate methods
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[[self tableView] beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
NSIndexSet * indexSet = [NSIndexSet indexSetWithIndex:sectionIndex];
switch (type) {
case NSFetchedResultsChangeInsert:
[[self tableView] insertSections:indexSet
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[[self tableView] deleteSections:indexSet
withRowAnimation:UITableViewRowAnimationFade];
break;
default:
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
NSArray * oldArray = nil;
if(indexPath) {
oldArray = [NSArray arrayWithObject:indexPath];
}
NSArray * newArray = nil;
if(newIndexPath) {
newArray = [NSArray arrayWithObject:newIndexPath];
}
switch(type) {
case NSFetchedResultsChangeInsert:
[[self tableView] insertRowsAtIndexPaths:newArray
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[[self tableView] deleteRowsAtIndexPaths:oldArray
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
{
UITableViewCell * cell = nil;
Message * message = nil;
cell = [[self tableView] cellForRowAtIndexPath:indexPath];
message = [[self fetchedResultsController] objectAtIndexPath:indexPath];
[cell setMessageText:[message msgText]];
}
break;
case NSFetchedResultsChangeMove:
[[self tableView] insertRowsAtIndexPaths:newArray
withRowAnimation:UITableViewRowAnimationFade];
[[self tableView] deleteRowsAtIndexPaths:oldArray
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[[self tableView] endUpdates];
}
那么,有人对我有提示吗,问题可能出在哪里?