0

私は現在、スキームを実装しようとしています:

MOC1 (PrivateQueue) -parent-> MOC2 (MainQueue) -parent-> MOC3 (PrivateQueue)、保存する PSC

ここに初期化コードがあります (MOC2 & MOC#:

_writeManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_writeManagedObjectContext.persistentStoreCoordinator = coordinator;
_writeManagedObjectContext.undoManager = nil;

_mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainManagedObjectContext.undoManager = nil;
_mainManagedObjectContext.parentContext = _writeManagedObjectContext;

ここにinit MOC1があります:

    _mocSSchild = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    _mocSSchild.undoManager = nil;
    _mocSSchild.parentContext = delegateMain.mainManagedObjectContext;

ここに保存があります:

    NSError *error = nil;
    [self.mocSSchild obtainPermanentIDsForObjects:self.mocSSchild.insertedObjects.allObjects error:&error];

    if (![self.mocSSchild save: &error]) {
    NSLog(@"Failed to save to FIRST data store: %@", [error localizedDescription]);
    NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
    if(detailedErrors != nil && [detailedErrors count] > 0)
    {
        for(NSError* detailedError in detailedErrors)
        {
            NSLog(@"  DetailedError: %@", [detailedError userInfo]);
        }
    }
    else
    {
        NSLog(@"  %@", [error userInfo]);
    }

    }
    AppDelegate *delegateMain = (AppDelegate *)[[NSApplication sharedApplication] delegate];
    if ([delegateMain.mainManagedObjectContext hasChanges] && ![delegateMain.mainManagedObjectContext save: &error]) {        NSLog(@"Failed to save to FIRST data store: %@", [error localizedDescription]);
    NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
    if(detailedErrors != nil && [detailedErrors count] > 0)
    {
        for(NSError* detailedError in detailedErrors)
        {
            NSLog(@"  DetailedError: %@", [detailedError userInfo]);
        }
    }
    else
    {
        NSLog(@"  %@", [error userInfo]);
    }
}
    if ([delegateMain.writeManagedObjectContext hasChanges] && ![delegateMain.writeManagedObjectContext save: &error]) {        NSLog(@"Failed to save to FIRST data store: %@", [error localizedDescription]);
    NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey];
    if(detailedErrors != nil && [detailedErrors count] > 0)
    {
        for(NSError* detailedError in detailedErrors)
        {
            NSLog(@"  DetailedError: %@", [detailedError userInfo]);
        }
    }
    else
    {
        NSLog(@"  %@", [error userInfo]);
    }
}

すべてのフェッチ要求は正しいブロックに配置されます (もちろん、フェッチ要求を実行するために mainManagedObjectContext に触れることはありません):

    __block NSError *error = nil;
    __block NSArray *findedResult = nil;
    [self.mocSSchild performBlockAndWait:^{
        findedResult = [self.mocSSchild executeFetchRequest:fetchRequest error:&error];
    }];

1回保存した後、メインキューでフリーズします(コアデータは、リクエストを行わないmainManagedObjectContextでフェッチリクエストを実行しようとするようです):

Call graph:
    2633 Thread_803320   DispatchQueue_173: NSManagedObjectContext Queue  (serial)
    + 2633 start  (in libdyld.dylib) + 1  [0x7fff8bb907e1]
    +   2633 main  (in callsfreecall) + 34  [0x10992c202]
    +     2633 NSApplicationMain  (in AppKit) + 869  [0x7fff8a49cbd6]
    +       2633 -[NSApplication run]  (in AppKit) + 517  [0x7fff8a4f81a3]
    +         2633 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]  (in AppKit) + 128  [0x7fff8a500df2]
    +           2633 _DPSNextEvent  (in AppKit) + 685  [0x7fff8a501533]
    +             2633 BlockUntilNextEventMatchingListInMode  (in HIToolbox) + 62  [0x7fff8f356ae3]
    +               2633 ReceiveNextEventCommon  (in HIToolbox) + 356  [0x7fff8f356c52]
    +                 2633 RunCurrentEventLoopInMode  (in HIToolbox) + 209  [0x7fff8f356eb4]
    +                   2633 CFRunLoopRunSpecific  (in CoreFoundation) + 290  [0x7fff9526c0e2]
    +                     2633 __CFRunLoopRun  (in CoreFoundation) + 1644  [0x7fff9526cb4c]
    +                       2633 _dispatch_main_queue_callback_4CF  (in libdispatch.dylib) + 275  [0x7fff8c4c20c8]
    +                         2633 _dispatch_client_callout  (in libdispatch.dylib) + 8  [0x7fff8c4bd0b6]
    +                           2633 _dispatch_barrier_sync_f_slow_invoke  (in libdispatch.dylib) + 77  [0x7fff8c4c2a2d]
    +                             2633 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0  (in CoreData) + 533  [0x7fff93d8b6c5]
    +                               2633 -[NSManagedObjectContext countForFetchRequest:error:]  (in CoreData) + 1563  [0x7fff93d65ddb]
    +                                 2633 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:]  (in CoreData) + 298  [0x7fff93d65f4a]
    +                                   2633 -[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]  (in CoreData) + 354  [0x7fff93d576c2]
    +                                     2633 _perform  (in CoreData) + 172  [0x7fff93d5787c]
    +                                       2633 _dispatch_barrier_sync_f_invoke  (in libdispatch.dylib) + 39  [0x7fff8c4be723]
    +                                         2633 _dispatch_client_callout  (in libdispatch.dylib) + 8  [0x7fff8c4bd0b6]
    +                                           2633 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke_0  (in CoreData) + 533  [0x7fff93d8b6c5]
    +                                             2633 -[NSManagedObjectContext countForFetchRequest:error:]  (in CoreData) + 1563  [0x7fff93d65ddb]
    +                                               2633 -[NSManagedObjectContext(_NSInternalAdditions) _countWithNoChangesForRequest:error:]  (in CoreData) + 298  [0x7fff93d65f4a]
    +                                                 2633 -[NSPersistentStoreCoordinator executeRequest:withContext:error:]  (in CoreData) + 1138  [0x7fff93d10ba2]
    +                                                   2633 -[_PFLock lock]  (in CoreData) + 24  [0x7fff93cfe548]
    +                                                     2633 pthread_mutex_lock  (in libsystem_c.dylib) + 536  [0x7fff92797dfd]
    +                                                       2633 __psynch_mutexwait  (in libsystem_kernel.dylib) + 10  [0x7fff938ca122]
4

1 に答える 1

1

まず、エラーを受け取ったときにエラーを処理する必要があります。現在、あなたは何もしていない、ログに記録していない、それらに反応していない、何もしていません。これは悪いです。エラーが発生しても、その兆候はまったくありません。次のステップに進むだけです。

次に、すべての MOC を同じキューに保存しています。プライベート MOC に対するアクティビティは、-performBlock:または-performBlockAndWait:メソッドを介してブロック内で実行する必要があります。

第 3 に、実行中のキューがわかりません。

インポート MOC は、非同期で実行されている操作またはブロック内で実行されている必要があります。インポート MOC は、プライベート MOC ではなく、スレッドの制限を使用する必要があります。インポート MOC が作業を完了すると、それ自体を保存し、メイン MOC を保存する必要があることをメイン キューに示す必要があります。

メイン MOC はメイン キューにのみ保存する必要があります。メイン MOC が保存を完了すると、その-performBlock:.

エラー結果で問題を修正し、作業を行っているキューを確認します。すべてがメイン キューにある場合、親/子 MOC は問題を解決しません。どこでどのような作業が行われているのかを再考する必要があります。

更新 1

まず、呼び出しの結果をリッスンしてエラーを検出できます。呼び出しが a を返す場合、BOOLそれは成功/失敗です。呼び出しが何か他のものを返した場合、それが他のものである場合、それはnil失敗であり、エラーが発生します。

あなたのコードは正しくありません。私が述べたように、スレッドの問題があります。プライベート MOC に直接触れていますが、これは正しくありません。おそらく他のエラーがありますが、このコードに基づいてそれらを見ることはできません。

「書き込み」MOC は、-performBlock:またはを介し​​てのみ操作する必要があり-performBlockAndWait:ます。この場合、 を使用する必要があります-performBlock:。直接触れています。それは悪いことです。

メイン MOC は、メイン キューまたは-performBlock:/経由でのみ操作する必要があります-performBlockAndWait:。このコードで直接触れているようです。

appDelegateシングルトンとしてアクセスしています。これはコードの悪臭です。調べて、依存性注入の使用を開始します。

子 moc は、スレッドに限定されたコンテキストである必要がある場合にプライベートとして設定され、理想的には NSOperation にある必要がある、それを作成したスレッドでのみアクセスする必要があります。

要するに、ここで見逃している核となる概念がたくさんあります。このようなコードを開発する前に、親/子コンテキストがどのように機能するかを理解し、キューとスレッドをよりよく理解する必要があります。

于 2013-06-26T22:14:59.347 に答える