2014-07-15 20 views
6

Tôi có một lỗi ngẫu nhiên đã khiến tôi thất vọng trong nhiều tháng mà tôi không thể hiểu được. Tôi sẽ nói rằng nó thất bại ít hơn 1 trong 1000 lần. Tôi phải có CoreData cấu hình không chính xác nhưng tôi không thể tìm ra hoặc tạo lại nó. Ý chính cơ bản là tôi nhận được một số thông tin từ máy chủ và sau đó tôi cập nhật một đối tượng CoreData trong một chủ đề nền. Đối tượng CoreData không cần thiết ngay lập tức cho giao diện người dùng.Cập nhật Chủ đề Nền của CoreData Có Ngẫu nhiên EXC_BAD_ACCESS KERN_INVALID_ADDRESS Lỗi

Tất cả điều này được thực hiện trong DataService có tham chiếu đến NSManagedObjectContext ban đầu được tạo trong AppDelegate. Lưu ý: Bất cứ điều gì mà tài liệu tham khảo [DataService sharedService] sử dụng AppDelegate.NSManagedObjectContext:

@interface DataService : NSObject {} 
    @property (nonatomic,strong) NSManagedObjectContext* managedObjectContext; 
@end 

Khi trở về máy chủ với dữ liệu phương pháp updateProduct được gọi là:

@implementation DataService 

    + (NSManagedObjectContext*) newObjectContext 
    { 
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];   //step 1 

    AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate]; 

    [context setPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator]; 
    [context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];    
    [appDelegate.managedObjectContext observeContext:context]; 

    return context; 
    } 

    +(void) saveContext:(NSManagedObjectContext*) context 
    { 
    NSError *error = nil; 
    if (context != nil) { 
     if ([context hasChanges] && ![context save:&error]) { 
     // Handle Error 
     } 
    } 
    } 

    +(void) updateProduct: (Product*) product 
    { 
    if(product == nil) 
     return; 

    //run in background 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void){ 

     //create private managed object 
     NSManagedObjectContext *context = [DataService newObjectContext]; 

     CoreDataProduct* coreProduct = [DataService product:product.productId withObjectContext:context]; 
     if(product != nil) 
     { 
     //copy data over from product 
     coreProduct.text = product.text; 

     //ERROR HAPPENS HERE on save changes 
     [DataService saveContext:context]; 
     } 

    //remove background context listening from main thread 
    [DataService.managedObjectContext stopObservingContext:context]; 

}); 
    } 

@end 

tôi sử dụng chung NSManagedObjectContext + Helper.h danh mục tệp nổi trên GitHub và lỗi EXC_BAD_ACCESS KERN_INVALID_ADDRESS của tôi xảy ra trong phương thức [DataService.managedObjectContext mergeChangesFromNotification: (NSNotification *)] gọi số này

@implementation NSManagedObjectContext (Helper) 

    - (void) mergeChangesFromNotification:(NSNotification *)notification 
    { 
    //ERROR HAPPENS HERE 
    [self mergeChangesFromContextDidSaveNotification:notification]; 
    } 

@end 

Tôi không thể hiểu tại sao phương thức mergeChangesFromContextDidSaveNotification không thành công một cách ngẫu nhiên. Tôi nghĩ rằng lỗi là do mất tham chiếu đến managedObjectContext được chia sẻ ban đầu. Mặc dù nếu đó là sự thật, tôi đoán tôi sẽ mong đợi các lỗi được trong phương pháp updateProduct và không phải trong lớp thể loại.

Tôi cho rằng cả phương thức newObjectContext và phương thức stopObservingContext đều tham chiếu đến managedObjectContext trên chuỗi nền từ chuỗi chính. Vì tôi đang tạo một managedObjectContext riêng, thậm chí tôi có cần phải làm cho bối cảnh chính được chia sẻ nhận biết về ngữ cảnh riêng tư không? Nếu vậy, tôi đang làm nó không chính xác?

Cảm ơn bạn đã trợ giúp.

+0

Có lẽ bạn nên hiển thị các phương pháp không, 'mergeChanges ...'. – Mundi

+0

Mục cuối cùng trong dấu vết ngăn xếp là - [NSManagedObjectContext _mergeChangesFromDidSaveDictionary: usingObjectIDs:] mà tôi không nghĩ là cung cấp nhiều thông tin. – dirkoneill

+0

Có lẽ bạn không nên sử dụng GCD nhưng các API tương thích ngữ cảnh như 'performBlock'. Ngoài ra, đặt một điểm ngắt tại dòng và kiểm tra thông báo. – Mundi

Trả lời

4

Nó xuất hiện vì NSManagedObjectContext mới đã được tạo trên luồng nền, bản gốc/gốc NSManagedObjectContext cần được quan sát trên chuỗi chính. Một khi tôi thay đổi observContext để quan sátContextOnMainThread, vấn đề CoreData này dường như đã biến mất. Tôi hi vọng điêu nay se giup được ai đo.

Dưới đây là phương pháp cập nhật của tôi:

+ (NSManagedObjectContext*) newObjectContext 
    { 
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];   //step 1 

    AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate]; 

    [context setPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator]; 
    [context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];    
    [appDelegate.managedObjectContext observeContextOnMainThread:context]; 

    return context; 
    } 
Các vấn đề liên quan