私はdispatch_queueを初めて使用し、バックグラウンドでCoreDataに保存しようとして問題に遭遇しました。CoreData プログラミング ガイドを読み、NSManagedObjectContext
バックグラウンド スレッドで別のスレッドを作成しています。テスト プロジェクトで sを作成する単純なループを実行するとNSManagedObject
、問題は発生しません。オブジェクトが作成され、 を使用しNSManageObjectContextDidSaveNotification
て変更をメイン スレッドに伝えます。
私の問題は、GCD を知らないことにあると思います。XML を解析していますparserDidEndDocument:
が、UI をブロックせずにデータを CoreData に保存する必要があります。このブロックが使用されるたびに、アプリのメモリが手に負えないほど雪だるま式に増え始め、最終的Terminated app due to memory pressure
に
注: AppDelegate のシングルトンを使用して my を保持し、NSPersistentStoreCoordinator
stuffToSave はNSMutablearray
パーサーによって作成されます。
どんな方向性でも大歓迎です。私は2日間頭を殴っています!
-(void)parserDidEndDocument:(NSXMLParser *)parser
dispatch_queue_t backgroundQ = dispatch_queue_create("com.example.myapp", NULL);
__block AppDelegate *app= [[UIApplication sharedApplication]delegate];
__block NSMutableArray *array = self.stuffToSave;
dispatch_async(backgroundQ, ^(void){
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
context.persistentStoreCoordinator = [app persistentStoreCoordinator];
HNField *field = [HNField fieldWithField_id:[NSNumber numberWithInt:0] inContext:context];
//initalize array if needed
if (!field.arrayOfPolylines) field.arrayOfPolylines = [[NSMutableArray alloc]init];
//add polyline to array to save in database
for (id obj in array) {
if ([obj isKindOfClass:[HNPolyline class]]) {
HNPolyline *theLine = (HNPolyline *)obj;
[field.arrayOfPolylines addObject:theLine];
}else if ([obj isKindOfClass:[HNParserPoint class]]){
HNPoint *point = [HNPoint createAPointWithContext:context];
HNParserPoint *pPoint = (HNParserPoint *)obj;
point.point_id = pPoint.point_id;
point.lat = pPoint.lat;
point.lng = pPoint.lng;
point.yield = pPoint.yield;
point.farm_id = self.farm_id;
point.field_id = self.field_id;
point.inField = field;
//add every point in database
[field addFieldPointsObject:point];
}
}
NSError *error;
[context save:&error];
});
self.stuffToSave = nil;
self.parser = nil;
}
編集 1:NSManageObjectContextDidSaveNotification
解析を行っている場所とは異なるクラスから
リッスンしています。私が持ってviewDidLoad
いる:
// observe the ParseOperation's save operation with its managed object context
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didSave:)
name:NSManagedObjectContextDidSaveNotification
object:nil];
次に、Apple の「ThreadedCoreData」の例から以下を使用しています。
-(void)didSave:(NSNotification *)notification{
if (notification.object != [self.app managedObjectContext]) {
NSLog(@"not main context");
[self performSelectorOnMainThread:@selector(updateMainContext:) withObject:notification waitUntilDone:NO];
}else{
NSLog(@"b Thread: %@",[NSThread currentThread]);
NSLog(@"main context");
}
}
// merge changes to main context
- (void)updateMainContext:(NSNotification *)notification {
assert([NSThread isMainThread]);
[[self.app managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
NSLog(@"did save");
}