核心数据崩溃:枚举时集合发生了变化

问题描述:

当我尝试执行提取时,我的应用似乎崩溃了。我正在使用神奇的记录。错误消息是:核心数据崩溃:枚举时集合发生了变化

收集< __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

究竟哪一行正在打破? –

我的问题,我在执行上下文保存并保存并发问题,我试图保存主线程上创建的对象不是主线程。将该代码移至主线程可修复崩溃。

+0

你移动到主线程的哪个代码?您在数据库中写入数据的代码或将数据保存在数据库中的代码? –

+0

上下文的实际创建都不是我所移动的:'NSManagedObjectContext context = [NSManagedObjectContext ...]' - >移动到主线程 – Minimi