0

私はコアデータプロジェクトを持っています。テーブル ビューをプルして更新すると、バックグラウンド スレッドで新しいコンテキストが作成され、データベースが更新され、それらの更新がメイン コンテキストにマージされます。すべてが正常に機能していました (と思います) が、次のようなクラッシュが発生しています。

2013-09-13 19:01:40.873 My App[2926:a0b] -[__NSCFString controllerWillChangeContent:]: unrecognized selector sent to instance 0xc26b370
2013-09-13 19:02:00.629 My App[2926:a0b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString controllerWillChangeContent:]: unrecognized selector sent to instance 0xc26b370'
*** First throw call stack:
(
    0   CoreFoundation                      0x027795e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x01e888b6 objc_exception_throw + 44
    2   CoreFoundation                      0x02816903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
    3   CoreFoundation                      0x0276990b ___forwarding___ + 1019
    4   CoreFoundation                      0x027694ee _CF_forwarding_prep_0 + 14
    5   CoreData                            0x002217b0 -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] + 2080
    6   Foundation                          0x015dbe39 __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke + 40
    7   CoreFoundation                      0x027d5524 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 20
    8   CoreFoundation                      0x0272d07b _CFXNotificationPost + 2859
    9   Foundation                          0x01515b91 -[NSNotificationCenter postNotificationName:object:userInfo:] + 98
    10  CoreData                            0x001264a3 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 83
    11  CoreData                            0x0013be96 -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 3734
    12  CoreData                            0x0013afed -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 429
    13  My App                            0x0000bc45 -[MAManager updateMainContext:] + 245
    14  libobjc.A.dylib                     0x01e9a81f -[NSObject performSelector:withObject:] + 70
    15  Foundation                          0x0155dc18 __NSThreadPerformPerform + 285
    16  CoreFoundation                      0x027028af __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
    17  CoreFoundation                      0x0270223b __CFRunLoopDoSources0 + 235
    18  CoreFoundation                      0x0271f30e __CFRunLoopRun + 910
    19  CoreFoundation                      0x0271eb33 CFRunLoopRunSpecific + 467
    20  CoreFoundation                      0x0271e94b CFRunLoopRunInMode + 123
    21  GraphicsServices                    0x0348e9d7 GSEventRunModal + 192
    22  GraphicsServices                    0x0348e7fe GSEventRun + 104
    23  UIKit                               0x0067b94b UIApplicationMain + 1225
    24  My App                            0x00003442 main + 146
    25  libdyld.dylib                       0x0236d725 start + 0
)
libc++abi.dylib: terminating with uncaught exception of type NSException

これは、壊れている関連するコードの一部です。

 // merge changes to main context,fetchedRequestController will automatically monitor the changes and update tableview.
- (void)updateMainContext:(NSNotification *)notification {
    assert([NSThread isMainThread]);
    NSLog(@"Merging changes from context.");
    [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
    [self save]; // update fetched results controllers
}

// this is called via observing "NSManagedObjectContextDidSaveNotification" from the background thread data load
- (void)mergeChangesFromContextDidSaveNotification:(NSNotification *)notification {
    NSLog(@"Context saved!");
    if (notification.object != [self managedObjectContext]) {
        NSLog(@"Background context propagating to main context.");
        [self performSelectorOnMainThread:@selector(updateMainContext:) withObject:notification waitUntilDone:NO];
    }
}

このエラーが発生する理由と修正方法を知っている人はいますか?

4

3 に答える 3

0

通知用に登録された一部のオブジェクトが解放されたように見え、そのアドレスが再利用されて、予期されたものではなく文字列が格納されます。

スキームのゾンビをオンにして再度実行し、通知が送信されているオブジェクトを特定します。次に、必要な間、オブジェクトを存続させていることを確認してください。

于 2013-09-13T23:24:22.230 に答える
0

複数の保存要求が同時に (管理対象オブジェクトのコンテキストは異なりますが、スレッドは異なるにもかかわらず) 入ってくるという問題があったようです。解決策は、保存操作を @synchronized ブロックでラップして、保存操作がアトミックであり、同時に発生しないようにすることでした。

- (void) save {
    // lock and wait if another save operation is in progress
    @synchronized([self class]) {
        NSError *error;
        if (![self save:&error]) {
            NSLog(@"Whoops, couldn't save: %@", error);
        }
    }
}
于 2013-09-15T21:03:57.723 に答える