핵심 데이터로 수행해야하는 큰 가져 오기 작업이 있습니다.
내 핵심 데이터 모델이 다음과 같다고 가정 해 보겠습니다.
Car
----
identifier
type
내 서버에서 자동차 정보 JSON 목록을 가져온 다음 핵심 데이터 Car
개체 와 동기화하고 싶습니다 . 즉
, 새 자동차 인 경우-> Car
새 정보에서 새 Core Data 개체를 만듭니다 .
자동차가 이미있는 경우-> Core Data Car
개체를 업데이트 합니다.
따라서 UI를 차단하지 않고 백그라운드에서이 가져 오기를 수행하고 사용하는 동안 모든 자동차를 표시하는 자동차 테이블보기를 스크롤합니다.
현재 나는 다음과 같이하고있다.
// create background context
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[bgContext setParentContext:self.mainContext];
[bgContext performBlock:^{
NSArray *newCarsInfo = [self fetchNewCarInfoFromServer];
// import the new data to Core Data...
// I'm trying to do an efficient import here,
// with few fetches as I can, and in batches
for (... num of batches ...) {
// do batch import...
// save bg context in the end of each batch
[bgContext save:&error];
}
// when all import batches are over I call save on the main context
// save
NSError *error = nil;
[self.mainContext save:&error];
}];
하지만 제가 여기서 옳은 일을하고 있는지 잘 모르겠습니다. 예를 들면 다음과 같습니다.
내가 사용해도 setParentContext
되나요?
나는 이것을 사용하는 몇 가지 예를 보았지만을 호출하지 않는 다른 예를 보았습니다 setParentContext
. 대신 다음과 같은 작업을 수행합니다.
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
bgContext.persistentStoreCoordinator = self.mainContext.persistentStoreCoordinator;
bgContext.undoManager = nil;
내가 확실하지 않은 또 다른 점은 주 컨텍스트에서 언제 save를 호출해야하는지입니다. 내 예에서는 가져 오기가 끝날 때 save를 호출하지만 다음을 사용하는 예를 보았습니다.
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification* note) {
NSManagedObjectContext *moc = self.managedObjectContext;
if (note.object != moc) {
[moc performBlock:^(){
[moc mergeChangesFromContextDidSaveNotification:note];
}];
}
}];
이전에 언급했듯이 업데이트하는 동안 사용자가 데이터와 상호 작용할 수 있기를 원하는데, 가져 오기가 동일한 차를 변경하는 동안 사용자가 차 유형을 변경하면 어떻게 작성합니까?
최신 정보:
@TheBasicMind의 훌륭한 설명 덕분에 옵션 A를 구현하려고하므로 코드는 다음과 같습니다.
다음은 AppDelegate의 핵심 데이터 구성입니다.
AppDelegate.m
#pragma mark - Core Data stack
- (void)saveContext {
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
DDLogError(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
// main
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedObjectContext.parentContext = [self saveManagedObjectContext];
return _managedObjectContext;
}
// save context, parent of main context
- (NSManagedObjectContext *)saveManagedObjectContext {
if (_writerManagedObjectContext != nil) {
return _writerManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_writerManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_writerManagedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _writerManagedObjectContext;
}
그리고 이것은 내 가져 오기 방법이 이제 어떻게 생겼는지입니다.
- (void)import {
NSManagedObjectContext *saveObjectContext = [AppDelegate saveManagedObjectContext];
// create background context
NSManagedObjectContext *bgContext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
bgContext.parentContext = saveObjectContext;
[bgContext performBlock:^{
NSArray *newCarsInfo = [self fetchNewCarInfoFromServer];
// import the new data to Core Data...
// I'm trying to do an efficient import here,
// with few fetches as I can, and in batches
for (... num of batches ...) {
// do batch import...
// save bg context in the end of each batch
[bgContext save:&error];
}
// no call here for main save...
// instead use NSManagedObjectContextDidSaveNotification to merge changes
}];
}
그리고 다음과 같은 관찰자가 있습니다.
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification* note) {
NSManagedObjectContext *mainContext = self.managedObjectContext;
NSManagedObjectContext *otherMoc = note.object;
if (otherMoc.persistentStoreCoordinator == mainContext.persistentStoreCoordinator) {
if (otherMoc != mainContext) {
[mainContext performBlock:^(){
[mainContext mergeChangesFromContextDidSaveNotification:note];
}];
}
}
}];