2013-07-14 1 views
1

응용 프로그램은 백그라운드에서 매 10 초마다 루프의 WebService에서 데이터를 업데이트하고 주 스레드에서 사용자의 요청으로 데이터를 사용자에게 표시해야합니다. 또한 사용자 요청에 의해 레코드를 업데이트하고 삭제해야합니다. runloop으로 업데이트가 완료되었습니다.IOS 멀티 스레딩 NSManagedObjectContext를 동기화하는 방법?

나는

NSOperationQueue* operationQueue; 

다음, 업데이트, 삽입 운영자는 모든 스레드에서이 방법을 추가 선택으로 내가 저장 sharedInstance 클래스를 가지고있는 AppDelegate에

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil]; 

- (void)contextChanged:(NSNotification*)notification 
{ 
    if ([notification object] == [self managedObjectContext]) return; 

    if (![NSThread isMainThread]) { 
     [self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES]; 
     return; 
    } 

    [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification]; 
    [self saveContext]; //do I need this here or marge save data too? 

} 

에 알림을 등록한 :

-(void)do_something 
{ 
    [self.operationQueue addOperationWithBlock:^{ 
    NSManagedObjectContext*moc; //creating new NSManagedObjectContext with AppDelegate.persistentStoreCoordinator 
    //do my staff 
    [moc save:&error] 
    }] 
} 

엔티티를 @ "my_id = % @", @ (my_id)로 업데이트하려고하면 문제가 발생합니다. 중복의

[moc countForFetchRequest:fetchRequest error:&error] 

반환 0 원인 삽입이 문제는 동기화이다 엔티티 존재한다. 조언하십시오. dispatch_queue_create ("com.my.", 0)의 인스턴스를 사용해야합니까? 대신 CoreData 연산마다?


내가

-(void)query:(void(^)(NSManagedObjectContext *context))queryBlock 
{ 
    NSLog(@"query CALL"); 
    __block NSManagedObjectContext *context; 
    //if remove dispatch_sync and/or run in main thread result the same 
    dispatch_sync(dispatch_queue_create("com.myapp.db-queue", 0), ^{ 
    AppDelegate*app = AppDelegate(); 

    //same result if I use 
    //app.persistentStoreCoordinator or 
    //[app.managedObjectContext persistentStoreCoordinator] 

    NSPersistentStoreCoordinator *persistentStoreCoordinator= [app.managedObjectContext persistentStoreCoordinator]; 

    context = [NSManagedObjectContext new]; 
    [context setPersistentStoreCoordinator:persistentStoreCoordinator]; 
    [context setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy]; 

    queryBlock(context); 
    if ([context hasChanges]) 
    { 
     NSError*err; 
     [context save:&err]; 
     if (err) { 
      NSLog(@"context save: %@",[err localizedDescription]); 
     } 
    } 
    }); 
} 

operationQuiue

을 제거 시도로 전화 않았다하시기 바랍니다

CoreStorage* cs = [CoreStorage sharedInstance]; 
NSArray* list = [ws GetSections]; //array of NSDictionaries 

//if add this to operationQuiue resunt the same 
[cs query:^(NSManagedObjectContext *moc) { 
NSLog(@"START"); 
for (NSDictionary *section in list) { 

    NSNumber* Id= @([[section objectForKey:@"section_id"] integerValue]); 

    NSFetchRequest * fetchRequest = [NSFetchRequest new]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Section" inManagedObjectContext: moc]; 
    [fetchRequest setEntity:entity]; 
    [fetchRequest setFetchLimit:1]; 
    [fetchRequest setIncludesSubentities:NO]; 
    [fetchRequest setPredicate: [NSPredicate predicateWithFormat:@"section_id=%@",Id]]; 

    NSError *error =nil; 
    Section *entry; 
    if ([moc countForFetchRequest:fetchRequest error:&error] >0) 
    { 
     entry = [moc executeFetchRequest:fetchRequest error:nil][0]; 
     NSLog(@"exist"); //this never call 
    } 
    else 
    { 
     entry = [NSEntityDescription insertNewObjectForEntityForName:@"Section" inManagedObjectContext:moc]; 
     NSLog(@"NEW"); 
    } 

    entry.section_id = Id; 
    entry.timeStamp = [NSDate date]; 
} 
}]; 

모든 sugastions?

+0

백그라운드에서 NSManagedObjectContext에 대해 NSMergeByPropertyStoreTrumpMergePolicy를 사용하고 AppDelegate의 주 스레드에 대해 NSMergeByPropertyObjectTrumpMergePolicy를 사용합니다. –

답변

0

문제가 작업 대기열에 있습니다. 최대 동시 작업을 1로 구성하지 않았습니까? 이 경우 직렬이 아니며 추가 한 연산이 동시에 실행됩니다. 그래서 여기에 어떻게됩니까? 첫 번째 연산은 ID가있는 객체 수를 가져 와서 찾지 못하고 하나를 만듭니다. 저장하기 전에 다른 작업이 추가됩니다. 이 두 번째 연산은 동일한 ID를 가진 객체를 가져오고 찾지 않고 하나를 만듭니다. 그런 다음 첫 번째 작업이 저장되고 두 번째 작업이 저장되고 복사본이 만들어집니다.

작업 대기 열을 [operationQueue maxConcurrentOperationCount:1];으로 만들어보십시오.

아니요, 관리 대상 개체 컨텍스트의 병합 메서드를 호출 한 후 저장하지 않아도됩니다.

+0

[operationQueue maxConcurrentOperationCount : 1]; - 나는 이걸했다. –

+0

설정에 NSFetchRequest가있는 것처럼 보입니다. DB에 데이터가 표시되지 않습니다. 나는 MOC의 문제를 추측한다. –

+0

가져 오기 요청은 항상 저장소의 최신 데이터를 확인해야합니다. – eofster