0

我在这里有一个(至少对我来说)奇怪的问题:

我有一个 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];
}

那么,有人对我有提示吗,问题可能出在哪里?

4

0 回答 0