2017-03-22 6 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の目的は別のスレッドでそのブロックを実行することなので、これは当てはまりません。

私が投稿した記事から、誰でも問題の内容を伝えることができますか?

更新:

- (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]; 
}]; 
} 

が、これはまだ失敗:

私は実行ブロックの外部にbuildFetchResultsControllerコールを移動しようとしました。私は上記のループで失敗を再現することができます。私はまた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)'のような構文を使ってある時点でセットを列挙しているようですが、このループの本体では 'objects 'を変更(追加/削除など)しています –

+0

そうです例外手段。しかし、これは意味をなさない。わかるように、このコード構造内にはどこにもループがないからです。フェッチ要求が – Minimi

+0

と呼ばれた後、エラーがスローされます。 –

答えて

2

私の問題は、私は、コンテキストに保存を実行していました保存に並行性の問題があった場合、メインスレッドで作成されたオブジェクトをメインではないスレッドから保存しようとしていました。そのコードをメインスレッドに移動するとクラッシュが修正されました。

+0

メインスレッドに移動したコードは?データをデータベースに書き込むコード、またはデータをデータベースに保存するコード? –

+0

コンテキストの実際の作成は移動しません: 'NSManagedObjectContext context = [NSManagedObjectContext ...]' - >メインスレッドに移動 – Minimi

関連する問題