0

私はここで(少なくとも私にとっては)ストランの問題を抱えています:

表示するデータを処理するためのNSFetchedResultsControllerを持つUITableViewControllerがあります。

表示する必要のあるデータはサーバーからのものであり、簡単にするために、一種のチャットだとしましょう。

簡略化されたモデルは次のように説明できます。

---------------           -----------------           -----------------
|  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)があります。新しいデータの挿入は、保存時にmainContextでmergeChangesFromContextDidSaveNotification:を呼び出す別のNSManagedObjectContextで行われます。

Threadクラスにはcompare:-メソッドがあるため、sortdescriptorにも使用できます。

UITableViewControllerに戻ります。

viewDidLoadで、topicIDのすべてのメッセージを取得するNSFetchedResultsControllerを作成し、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                          |
|____________________________________|

ご覧のとおり、最初のスレッドのセクションヘッダーが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