3

사과 문서를 읽었지만 여전히 답변을 찾을 수 없다는 질문이 있습니다. 두 개의 중첩 된 컨텍스트가있는 UIManagedDocument 개체가 있습니다. 자식 스레드는 주 스레드에 있고 부모 스레드는 개인 스레드에 있습니다. 그리고 나서, 나는 서버 쪽을 가졌다. 그래서, 서버에서 데이터가 도착하면 배경 스레드에서 관리되는 문서에 삽입하려고합니다.UIManagedDocument 중첩 된 컨텍스트

비동기식 대기열을 만들고 거기에 NSManagedObjectContext를 만들고 스레드로 만든 상위 UIManagedDocument의 하위 컨텍스트로 설정하면 스레드로부터 안전합니까? 즉

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL); 
dispatch_async(fetchQ, ^{ 
    //here goes some code for downloading data from the server 

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    [backgroundContext setParentContext:self.eventDatabase.managedObjectContext]; // is this thread safe? 

    //some code for creating objects in backgroundContext 

    NSLog(@"inserting data in background thread"); 


}); 
dispatch_release(fetchQ); 

는 - 그는 주 스레드에서 만들어진, 그것은 개인 스레드 부모에 생성 된 컨텍스트에 할당 할 스레드 안전입니까?

답변

4

개인 동시성 유형을 사용 중입니다. 즉, performBlock을 통해 자체 대기열에서 코드를 실행해야합니다. 당신이 그렇게 할 경우 큐를 직접 관리 할 경우, 당신은 아마 감금 MOC를 사용해야합니다

NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
backgroundContext.parentContext = self.eventDatabase.managedDocument; 
backgroundContext.performBlock:^{ 
    //here goes some code for downloading data from the server 
    //some code for creating objects in backgroundContext 

    NSLog(@"inserting data in background thread"); 

    // Calling save on the background context will push the changes up to the document. 
    NSError *error = nil; 
    [backgroundContext save:&error]; 

    // Now, the changes will have been pushed into the MOC of the document, but 
    // the auto-save will not have fired. You must make this call to tell the document 
    // that it can save recent changes. 
    [self.eventDatabase updateChangeCount:UIDocumentChangeDone]; 
}); 

그래서, 당신은 ... 이런 식으로해야합니까, 당신은 NSConfinementConcurrencyType로 초기화하기, 또는으로한다 기본 init이기 때문에 표준 init입니다. 그러면 다음과 같이 보일 것입니다 ...

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL); 
dispatch_async(fetchQ, ^{ 
    backgroundContext.parentContext = self.eventDatabase.managedDocument; 

    //here goes some code for downloading data from the server 

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] init]; 

    // Everything else is as in the code above for the private MOC. 
}); 
dispatch_release(fetchQ); 
+0

[backgroundContext save : & error]를 반드시 호출해야합니다. 그렇지 않으면 변경 사항이 부모 컨텍스트로 푸시되지 않습니다. –

+0

그는 단지 UIManagedDocument의 parentContex를 사용하지 않습니다.이 컨텍스트는 백그라운드에서 실행됩니까? –

0

아니요 Andrew managedobjectcontext는 스레드로부터 안전하지 않습니다. 원하는 것을 얻기 위해 child managedcontext를 작성해야하며, 물건을 만든 다음 하위 및 상위 컨텍스트에 변경 사항을 저장하십시오. 저장은 변경 사항을 한 단계 위로 푸시한다는 점을 기억하십시오.

NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
[addingContext setParentContext:[self.fetchedResultsController managedObjectContext]]; 

[addingContext performBlock:^{ 
    // do your stuffs 
    [addingContext save:&error]; 

    [parent performBlock:^{ 
     [parent save:&parentError]; 
    }]; 
}]; 
관련 문제