2

この問題を解決する方法がわかりません。このコードは、ユーザーがスクロールするたびに各セルで実行され、UITableView に表示されます。

self.isFinishedProcessing = NO;

    [self setNeedsDisplay];

    [self.mediaArray removeAllObjects];
    self.mediaArray = [[NSMutableArray alloc] init];

    dispatch_queue_t queue = dispatch_queue_create("setup_cell", NULL);

    NSManagedObjectID *objectID = [self.entry objectID];
    dispatch_async(queue, ^{

        CoreDataStore *customStore = [CoreDataStore createStore];

        Entry *entry = (Entry *)[customStore.context objectWithID:objectID];

        if (self.cellInfo.numberOfMediaItems > 0) {

            int i = 0;

            int numberOfThumbnails = MIN(self.cellInfo.numberOfMediaItems, 3);

            while (i < numberOfThumbnails) {
                Media *media = [entry.media objectAtIndex:i];

                UIImage *image = [media getThumbnail];
                [self.mediaArray addObject:image];

                i++;
            }
        }

        dispatch_async(dispatch_get_main_queue(), ^{

            self.isFinishedProcessing = YES;
            [self setNeedsDisplay];
        });

    });

コア データ ストアは、コア データ クラスである Entry を Media と共に取得し、独自のコンテキストに配置します。

スクロール時にこのコードがいつクラッシュするかは正確にはわかりませんが、上下に数回スクロールすると発生します。

編集: 'object at index' の前の NSLog は、カウントが 3 であると言っています。

エラーの全文は次のとおりです。

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

編集2:

この問題はまだ解決していません。最後にこれを追加しました:

        if (self.mediaArray.count != self.entry.media.count) {
        NSLog(@"INCORRECT BECAUSE.... media array count: %i, entry media count: %i number of media items: %i", self.mediaArray.count, self.entry.media.count, self.cellInfo.numberOfMediaItems);
        }

そして、次のようなセルの後にクラッシュすることがよくあります。

INCORRECT BECAUSE.... media array count: 1, entry media count: 3 number of media items: 3

self.cellInfo.numberOfMediaItems に依存して作成された場合、メディア配列のカウントがどのように間違っている可能性があるのか​​ わかりません。

また、これは別のスレッドで実行された場合にのみ発生することにも注意してください。メインスレッドでクラッシュすることはありません。

4

1 に答える 1

6

複数のスレッドで Core Data のルール #1に違反しています。

そのスレッドで作成されたものでない限り、スレッドで MOC を使用してはなりません。

いくつかの作業を実行するキューを作成します...

dispatch_queue_t queue = dispatch_queue_create("setup_cell", NULL);

そして、そのブロックでは、そこで作成されていないMOCを使用しています...

Entry *entry = (Entry *)[customStore.context objectWithID:objectID];

MOC で作業を行う場合は、ルールに従う必要があります。ルール 1にはいくつかの節があるため、要約します。

  • で MOC を作成した場合、そのコンテキストをNSConfinementConcurrencyType呼び出すことはできません。それを作成したスレッド内でのみ使用 する必要performBlockがあります。

  • を使用する場合は、メイン スレッド内から、または 経由で MOC にアクセスするNSMainQueueConcurrencyType必要があり[moc performBlock]ます。

  • を使用する場合はNSPrivateQueueConcurrencyType、経由でのみ使用する必要[moc performBlock]があります。

編集

アイテムが同期されていません。データが実際に伝えていることだけを当てにすべきです。明らかに、self.cellInfo.numberOfMediaItems からのカウントを数えていますが、実際のデータとは同期していません。

複数のスレッドからデータを更新する場合は、十分に注意する必要があります。あなたのコードは、実際に何が起こっているのかを「追跡できなくなりました」。おそらく、データをプルしているコンテキストにまだ保存していないためです。

Core Data と同時実行に関するドキュメントを読んでください。他のすべてのコンテキストに通知せずに、別のスレッドで何も変更していないことを確認してください。親/子コンテキストを使用するか、DidSave 通知を処理して、データの同期を維持する必要があります。

于 2012-06-02T22:56:20.153 に答える