Лучшая практика в контексте базовых данных

У меня есть большая задача импорта, которую я должен сделать с основными данными.
Допустим, моя основная модель данных выглядит следующим образом:

Car
----
identifier 
type

Я получаю список информации об автомобиле JSON с моего сервера, а затем хочу синхронизировать его с основными даннымиCar объект, значение:
Если это новый автомобиль -> создать новые базовые данныеCar объект из новой информации.
Если автомобиль уже существует -> обновить основные данныеCar объект.

Поэтому я хочу выполнить этот импорт в фоновом режиме, не блокируя пользовательский интерфейс и пока пользователь прокручивает табличное представление автомобилей, в котором представлены все автомобили.

В настоящее время я делаю что-то вроде этого:

// 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];
            }];
        }
    }
}];

Ответы на вопрос(3)

Ваш ответ на вопрос