2017-03-22 48 views
0

當我嘗試執行提取時,我的應用似乎崩潰了。我正在使用神奇的記錄。錯誤消息是:核心數據崩潰:枚舉時集合發生了變化

收集< __NSCFSet:0x17005a1f0>被列舉時發生了變異。

對我來說,這表明我們在執行提取時正在更改上下文中的對象,但我是新來的,所以我可能是錯的。

下面是它的指向代碼:

- (void) buildAndFetchFRCsInContext:(NSManagedObjectContext*)context{ 

[context performBlock:^{ 
    __unused NSDate* start = [NSDate date]; 

    self.contactsFRC = [self buildFetchResultsControllerForClass:[Contact class] sortedBy:@"id" withPredicate:nil inContext:context]; 
    self.callsFRC = [self buildFetchResultsControllerForClass:[Call class] sortedBy:@"id" withPredicate:nil inContext:context]; 
    self.newsItemsFRC = [self buildFetchResultsControllerForClass:[NewsItem class] sortedBy:@"id" withPredicate:nil inContext:context]; 

    NSError* error; 

    // Peform the fetches 
    [self.contactsFRC performFetch:&error]; 
    [self.callsFRC performFetch:&error]; 
    [self.newsItemsFRC performFetch:&error]; //Crash points to this line 
    NSLog(@"Spent [%@s] performing fetchs for counts!", @(fabs([start timeIntervalSinceNow]))); 

    [self calculateAndBroadcastCounts]; 
}]; 
} 

上下文中傳遞的是:

- (instancetype) initWithUserSession:(BPDUserSession*)userSession{ 
    self = [super init]; 
    ... 
    self.context = [NSManagedObjectContext MR_context]; 
    [self buildAndFetchFRCsInContext:self.context]; 
    ... 
} 

我覺得是,這個類是在主線程中被初始化,但performBlock增加將該塊放入隊列中,然後從不同的線程執行。但我不認爲這是真的,因爲performBlock的目的是在另一個線程上執行該塊。

從我發佈的內容,誰能告訴問題是什麼?

更新:

我試過buildFetchResultsController呼叫移動到執行塊外:

- (void) buildAndFetchFRCsInContext:(NSManagedObjectContext*)context{ 
self.contactsFRC = [self buildFetchResultsControllerForClass:[Contact class] sortedBy:@"id" withPredicate:nil inContext:context]; 
self.callsFRC = [self buildFetchResultsControllerForClass:[Call class] sortedBy:@"id" withPredicate:nil inContext:context]; 
self.newsItemsFRC = [self buildFetchResultsControllerForClass:[NewsItem class] sortedBy:@"id" withPredicate:nil inContext:context]; 

NSMutableArray *list = [[NSMutableArray alloc] initWithCapacity:100]; 
for (int i = 0; i < 100; i++) { 
    list[i] = [self buildFetchResultsControllerForClass:[NewsItem class] sortedBy:@"id" withPredicate:nil inContext:context]; 
} 

[context performBlock:^{ 
    __unused NSDate* start = [NSDate date]; 

    NSError* error; 

    // Peform the fetches 
    [self.contactsFRC performFetch:&error]; 
    [self.callsFRC performFetch:&error]; 
    [self.newsItemsFRC performFetch:&error]; 

    for (int i = 0; i < list.count; i++) { 
     [list[i] performFetch:&error]; // Generally error is thrown on i = 5 ~> 10 
    } 

    NSLog(@"Spent [%@s] performing fetchs for counts!", @(fabs([start timeIntervalSinceNow]))); 

    [self calculateAndBroadcastCounts]; 
}]; 
} 

,但仍然失敗。我能夠通過上面顯示的循環重現失敗。我也嘗試創建一個新的上下文,使用NSPrivateQueueConcurrencyType的實際performBlock關閉,但這也沒有工作,同樣的問題。

注:我使用MagicalRecords,所以對於那些你們誰不熟悉,[NSManagedObjectContext MR_context];相當於從上下文返回:

NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; // Here self is NSManagedObjectContext 
[context setParentContext:parentContext]; 
[context MR_obtainPermanentIDsBeforeSaving]; 
return context; 
+0

這看起來像你在使用類似'for(MyClass * object in object)'的語法枚舉一個集合'然後在這個循環的主體中你正在修改(添加/刪除等)'對象' –

+0

是的,這是什麼例外的意思。但是這沒有任何意義,因爲如你所見,在這個代碼結構中沒有任何地方存在循環。在獲取請求被調用後拋出錯誤 – Minimi

+0

究竟哪一行正在打破? –

回答

2

我的問題,我在執行上下文保存並保存併發問題,我試圖保存主線程上創建的對象不是主線程。將該代碼移至主線程可修復崩潰。

+0

你移動到主線程的哪個代碼?您在數據庫中寫入數據的代碼或將數據保存在數據庫中的代碼? –

+0

上下文的實際創建都不是我所移動的:'NSManagedObjectContext context = [NSManagedObjectContext ...]' - >移動到主線程 – Minimi

相關問題