3

私の UITableViewCell のコンテンツ作成の一部は、1 つのオブジェクト (CoreData NSManagedObject) の初期アクセスで発生する障害によって遅延します。これは、セルが最初にスクロールされて表示されるときの小さな問題として現れます。これらのオブジェクトへのアクセスをバックグラウンド スレッドにプッシュすることにしました。

これは私が実装した方法であり、うまく機能しますが、別のスレッドで 1 つのスレッド (メイン スレッド) の NSManagedObjectContext にアクセスすることは想定されていませんが、次の場合に 2 番目のスレッドでオブジェクトの objectID を取得できますか?もともと最初のスレッドで取得されたものですか?

objectID の取得には少し時間がかかりますが、これは他のすべてのものと一緒にバックグラウンドにプッシュすることを望んでいました。

MyRecord *record = [self.frc objectAtIndexPath: indexPath];

// Should the following be here or can it be below in the background thread?
// NSManagedObjectID *recordObjectID = record.objectID;

dispatch_async(_recordViewQueue, ^(void) {
    if ([cell.origIndexPath isEqual:indexPath]) {

        // should the following be here or above?  It works here, but am I just lucky?
        // this call seems to take about 2/100 of a second
        NSManagedObjectID *recordObjectID = record.objectID;

        NSManagedObjectContext *bgndContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
        bgndContext.persistentStoreCoordinator = App.sharedApp.storeCoordinator;
        MyRecord *newRecord = (MyRecord *) [bgndContext objectWithID:recordObjectID];

        [self updateCell:cell withRecord:newRecord];

        if ([cell.origIndexPath isEqual:indexPath]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [(UIView*) cell.recordView setNeedsDisplay];
            });
        }
    }
});

これは安全ですか?または、mainThread で objectID を取得する必要がありますか?

4

1 に答える 1

5

管理対象オブジェクトの objectID をスレッド間で安全に渡すことができます。スレッド間でマネージド オブジェクトを使用するのは安全ではありません。objectID とスレッドのマネージド オブジェクト コンテキストを使用して、existingObjectWithID:error: を呼び出し、そのスレッドのマネージド オブジェクトのインスタンスを取得します。

コードを次のように更新します。

MyRecord *record = [self.frc objectAtIndexPath: indexPath];

NSManagedObjectID *recordObjectID = record.objectID;

dispatch_async(_recordViewQueue, ^(void) {
    if ([cell.origIndexPath isEqual:indexPath]) {

        NSManagedObjectContext *bgndContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
        bgndContext.persistentStoreCoordinator = App.sharedApp.storeCoordinator;
        NSError * error = nil;
        MyRecord *newRecord = (MyRecord *) [bgndContext existingObjectWithID:recordObjectID error:&error];
        if (newRecord) {
            [self updateCell:cell withRecord:newRecord];
            if ([cell.origIndexPath isEqual:indexPath]) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    [(UIView*) cell.recordView setNeedsDisplay];
                });
            }
        }
        else {
            NSLog(@"unable to find existing object! error: %@ (userInfo: %@)", [error localizedDescription], [error userInfo]);
        }
    }
});
于 2013-07-30T22:17:07.967 に答える