2012-02-10 51 views
3

嘗試合併託管上下文(在後臺線程上運行)和主託管上下文(在mainthread上)時,會出現以下異常。我似乎無法捕捉我自己的@try表達式中的異常。有沒有人對此問題有所瞭解?合併CoreData託管上下文時發生異常/崩潰

我使用默認的合併策略,但我不知道這是否正確 - 這個問題是非常間歇的 - 很少發生,但導致我的應用程序崩潰。

Exception Type: EXC_CRASH (SIGABRT) 
Exception Codes: 0x00000000, 0x00000000 
Crashed Thread: 0 

Last Exception Backtrace: 
0 CoreFoundation     0x37e3b8bf __exceptionPreprocess + 163 
1 libobjc.A.dylib     0x319211e5 objc_exception_throw + 33 
2 CoreData      0x344b7ea5 -[NSSQLiteStatement cachedSQLiteStatement] + 1 
3 CoreData      0x344b774f -[NSSQLiteConnection prepareSQLStatement:] + 55 
4 CoreData      0x3455b049 -[NSSQLChannel selectRowsWithCachedStatement:] + 61 
5 CoreData      0x34586d63 newFetchedRowsForFetchPlan_MT + 783 
6 CoreData      0x344bfb07 -[NSSQLCore newRowsForFetchPlan:] + 351 
7 CoreData      0x34565011 -[NSSQLCore fetchRowForObjectID:] + 1005 
8 CoreData      0x344d1a57 -[NSSQLCore newValuesForObjectWithID:withContext:error:] + 195 
9 CoreData      0x344d0f83 _PFFaultHandlerLookupRow + 423 
10 CoreData      0x3450e111 -[NSFaultHandler fulfillFault:withContext:] + 25 
11 CoreData      0x34518999 -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:] + 77 
12 CoreData      0x345178ef -[NSManagedObject(_NSInternalMethods) _newAllPropertiesWithRelationshipFaultsIntact__] + 79 
13 CoreData      0x345284db -[NSManagedObjectContext(_NSInternalChangeProcessing) _establishEventSnapshotsForObject:] + 47 
14 CoreData      0x3452694b -[NSManagedObjectContext deleteObject:] + 155 
15 CoreData      0x345238a1 -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 813 
16 CoreData      0x34522c35 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 189 
17 myapp      0x0008f0e9 0x8d000 + 8425 
18 CoreFoundation     0x37d9a22b -[NSObject performSelector:withObject:] + 43 
19 Foundation      0x31d75757 __NSThreadPerformPerform + 351 
20 CoreFoundation     0x37e0fb03 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 
21 CoreFoundation     0x37e0f2cf __CFRunLoopDoSources0 + 215 
22 CoreFoundation     0x37e0e075 __CFRunLoopRun + 653 
23 CoreFoundation     0x37d914dd CFRunLoopRunSpecific + 301 
24 CoreFoundation     0x37d913a5 CFRunLoopRunInMode + 105 
25 GraphicsServices    0x3790ffcd GSEventRunModal + 157 
26 UIKit       0x35221743 UIApplicationMain + 1091 

我初始化後臺上下文開始()像這樣一個的NSOperation的:

AppDelegate *appController = [[UIApplication sharedApplication] delegate]; 
_managedObjectContext = [[NSManagedObjectContext alloc] init]; 
[appController setPersistentStore:_managedObjectContext]; 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedDeletedObjects:) name:NSManagedObjectContextDidSaveNotification object:_managedObjectContext]; 

我還設置了當對象在背景管理上下文刪除其被稱爲通知事件,則回調然後做:

-(void)receivedDeletedObjects:(NSNotification *)note 
{ 
    AppDelegate *appController = [[UIApplication sharedApplication] delegate]; 
NSManagedObjectContext *mainContext = [self managedObjectContext]; 
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:note waitUntilDone:NO]; 

} 

這幾乎是代碼。我有4個不同的後臺線程,每個都有自己的託管上下文,以這種方式合併主要上下文。我想知道多個線程正在同時進入mergeChangesFromContextDidSaveNotification,但這不應該是這種情況,因爲它總是在mainthread上調用。

+0

某些源代碼會很有用,特別是在您進行合併並創建附加上下文的情況下。 – twilson 2012-02-10 20:44:54

+0

hi twilson ive添加了上面的代碼.. – mike 2012-02-10 21:36:13

+0

出於興趣,你爲什麼要調用'performSelectorOnMainThread:withObject:waitUntilDone:'因爲真的所有這些都應該在主線程上發生了? – twilson 2012-02-10 21:47:13

回答

0

如何:

(都在AppDelegate中,從後臺線程調用freshContextForBackgroundTask並使用保存:觸發合併)注意syncObj是使用許多當應用程序委託中需要同步的純NSObject的實例後臺線程(或只是有調度運氣不好)

-(NSManagedObjectContext*) freshContextForBackgroundTask { 
    @synchronized(syncObj) { 
     NSManagedObjectContext* r = [[NSManagedObjectContext alloc] init]; 
     [r setPersistentStoreCoordinator:self.managedObjectContext.persistentStoreCoordinator]; 
     [[NSNotificationCenter defaultCenter] addObserver:self 
               selector:@selector(backgroundContextDidSave:) 
                name:NSManagedObjectContextDidSaveNotification 
                object:r]; 
     return r; 
    } 
} 


- (void)backgroundContextDidSave:(NSNotification *)notification { 
    /* Make sure we're on the main thread when updating the main context */ 
    //NSLog(@"merging change: %@",notification); 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSManagedObjectContext *context = [self managedObjectContext]; 
     // this for loop may not be needed for your purpose. 
     for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) { 
      [[context objectWithID:[object objectID]] willAccessValueForKey:nil]; 
     } 
     [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification]; 

    }); 
} 

你的方法似乎很奇怪。尤其是當您將應用程序委託的持久性存儲設置爲新近啓動的上下文(nil)時。

相關問題