2012-09-24 2 views
10

나는 MagicalRecord 2.0.3를 사용하고 있는데 정말 백그라운드에서 데이터를 저장하는 방법을 알아낼 수 없습니다.있는 배경에서 여러 개체를 만드는 방법?

문서에 따르면,이 같은 작업을해야합니다 :

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) { 
    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 
}]; 

그러나, 아무것도 데이터베이스에 저장되지 않습니다. 내가 여러 사람이 이와 비슷한 솔루션을 게시 본 적이 :

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *localContext) { 
    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 
} completion:^{ 
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
     [[NSManagedObjectContext defaultContext] saveNestedContexts]; 
    }]; 
}]; 

이 내 데이터 집합 (저장이 주 스레드에서 발생하기 때문에 그러나, 내 응용 프로그램은 잠시 동안 응답하지 않는 데이터베이스 내 데이터를 저장하지 않습니다, 길지 않은 약 3 초).

나는이 시도했다, 그러나 그것은 또한 블록까지 저장하는 동안 :

self.queue = [[NSOperationQueue alloc] init]; 

[self.queue addOperationWithBlock:^{ 
    NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread]; 

    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 

    [localContext saveNestedContexts]; 
}]; 

그리고 마지막으로,이 코드와 같은 차단 효과 :

dispatch_queue_t syncQueue = dispatch_queue_create("Sync queue", NULL); 
dispatch_async(syncQueue, ^{ 
    NSManagedObjectContext *localContext = [NSManagedObjectContext contextForCurrentThread]; 

    // Do this hundreds of times 
    [MyObject createInContext:localContext]; 

    [[NSManagedObjectContext contextForCurrentThread] saveNestedContexts]; 
}); 

그래서 가장 좋은 방법은 무엇입니까 이 문제를 해결하려면? 백그라운드에서 수백 개의 개체를 만들어야하고 앱이 응답 성을 유지해야합니다. 백그라운드에서 작업을 수행 할 때

+0

일할 수있는 새로운 중첩 된 상황이 MagicalRecord에 저장하는 API의 대부분에 위력을 과시하기 시작했다 방법의 예를 찾을 수 있습니다. 이 문제를 알고 있고 수정 사항에 대해 지금 논의 중이지만 언제나 제안에 대해 열려 있습니다. – casademora

+2

아마도 MR과 같은 프레임 워크없이 핵심 데이터를 사용하는 것이 가장 좋습니다. – Hunter

+0

MagicalRecord를 사용하여 해결책을 찾았습니까? 동일한 문제 (백그라운드에서 업데이트하는 동안 UI 잠김)가 있고 솔루션을 찾을 수 없습니다. 감사! – RyanG

답변

6

MagicalRecord 아이 컨텍스트를 사용합니다. 이것은 작은 변경에 대해서는 문제가 없지만 많은 양의 데이터를 가져올 때 과도한 주 스레드 차단을 생성합니다.

병렬 NSManagedObjectContext를 사용하고 NSManagedObjectContextDidSaveNotification 알림 및 mergeChangesFromContextDidSaveNotification 메서드를 사용하여 병합하는 방법이 있습니다. 여기에 성능 테스트를 참조하십시오 http://floriankugler.com/blog/2013/5/11/backstage-with-nested-managed-object-contexts

중첩 된 컨텍스트의 모든 것을 절약 부모 컨텍스트에 복사해야합니다. 이와는 반대로, (당신이 병합되는으로 맥락에서) 가져되지 않은 객체는 mergeChangesFromContextDidSaveNotification에 의해 병합되지 않습니다. 이것은 그것을 더 빨리 만드는 것입니다. 당신이 바로 일괄 저장하고 NSFetchResultsController 사용 후 결과를 표시하려면

당신은 문제가 발생할 수 있습니다. 솔루션을 다음과 같은 질문을 참조하십시오 : 더 성능 정보에 대한 NSFetchedResultsController with predicate ignores changes merged from different NSManagedObjectContext

이 질문에 대해 살펴 : Implementing Fast and Efficient Core Data Import on iOS 5

자신의 컨텍스트를 만듭니다.

NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] 
          initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
[importContext setPersistentStoreCoordinator:yourPersistentStoreCoordinator]; 
[importContext setUndoManager:nil]; // For importing you don't need undo: Faster 

// do your importing with the new importContext 
// … 

NSError* error = nil; 
if(importContext.hasChanges) { 
    if(![importContext save:&error]) { 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    } 
} 

관리 대상 개체 컨텍스트에 대한 수신 대기 중인지 확인하십시오.

[[NSNotificationCenter defaultCenter] 
       addObserver:singleton 
       selector:@selector(contextDidSave:) 
        name:NSManagedObjectContextDidSaveNotification object:nil]; 

: 직접 변경 사항을 병합합니다. 혹시 당신의 Coredata 객체와 배경 작업의 종류를 할 필요가 그래서 만약

- (void) contextDidSave:(NSNotification*) notification 
{ 
    if(![notification.object isEqual:self.mainContext]) { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.mainContext mergeChangesFromContextDidSaveNotification:notification]; 
    }); 
    } 
} 
+0

정확히 어떻게 작동합니까? 대량의 데이터를 가져 오기 때문에 메인 스레드가 블로킹하는 문제에 직면하고 있습니다. MagicalRecord를 사용하고 있지만 여기서 작성한 것을 성취 할 수는 없습니다. – swalkner

+0

@swalkner 자세한 내용을 제공하는 답변을 편집했습니다. – Onato

1

관리 객체 컨텍스트는 스레드로부터 안전하지 않습니다 (즉, 메인 UI를 차단하지 않고 장기 실행 가져 오기/내보내기 기능) 당신이 원하는 것 그 배경 스레드.

이러한 경우 백그라운드 스레드에서 새 관리 객체 컨텍스트를 만들고 코어 데이터 작업을 반복 한 다음 변경 사항을 주 컨텍스트에 알릴 필요가 있습니다.

당신이 여기

Core Data and threads/Grand Central Dispatch

관련 문제