Подтвердить что ты не робот

Основные данные iOS при сохранении контекста?

У меня случайные сбои с основными данными из-за concurrency и многопоточности. Я знаю, что основные данные не являются потокобезопасными. Я также нашел пару других ответов о том, как создать ThreadedDataService и создать отдельный контекст для каждого потока.

Это слишком много для меня, чтобы усвоить на данный момент, поэтому я пытаюсь найти более простой выход.

Решение, которое я пытаюсь сделать на данный момент, прост: сохранение данных через основной поток. Однако теперь возникает новая проблема: тупик. Приложение становится невосприимчивым, потому что за каждой из моих вставок нового NSManagedObject следует вызов для сохранения. (это мое лучшее предположение).

Чтение документации делегата приложения, я заметил, что он рекомендует мне сохранять контекст в applicationWillTerminate.

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

-(void)insertNewEvent
{


    // Create a new instance of the entity managed by the fetched results controller.
    NSManagedObjectContext *context = [self.fetchedResultsController.managedObjectContext];
    NSEntityDescription *entity = [[self.fetchedResultsControllerfetchRequest] entity];
    Event*newManagedObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

//use accessor methods to set default values

    // Save the context. > IS THIS REALLY NEEDED HERE?
    NSError *error = nil;
    if (![context save:&error])
    {


    }else
    {
        if(newManagedObject!=nil)
        {
            currentState= newManagedObject;
            [currentRecord addEvent:newManagedObject];
//Is this call needed?
            [self saveApplicationRecords];      
        }
    }

}

У меня есть методы, подобные этим для всех моих управляемых объектов, достаточно ли этого, если я вызываю такой метод в основном потоке каждые 10-15 минут, чтобы сохранить ожидающие изменения, а не делать это после каждой записи?

-(void)saveApplicationRecords
{
     NSLog(@"saveApplicationRecords");
    NSManagedObjectContext *context = [self.applicationRecordsController.managedObjectContext];
    // Save the context.
    NSError *error = nil;
    if (![context save:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

    }

}

Дополнительный вопрос после чтения ответа macbirdie: является ли этот метод законным в основных данных?

-(Event*)insertAndReturnNewEventWithDate:(NSDate*)date_ type:(int)type
{
 NSManagedObjectContext *context = [self.dreamEventsController managedObjectContext];
    NSEntityDescription *entity = [[self.dreamEventsController fetchRequest] entity];
    DreamEvent *newManagedObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

//handle properties

 NSError *error = nil;
    if (![context save:&error])
    {
return nil;

    }else
    {
return newManagedObject ;
}

}

Спасибо!

4b9b3361

Ответ 1

Вам не нужно сохранять контекст в начале процесса, особенно если вы хотите впоследствии изменить объект.

В большинстве случаев вам необходимо создать отдельный NSManagedObjectContext для изменений, которые вы собираетесь выполнить в базе данных. Поэтому создайте на нем объекты, заполните необходимые свойства, затем отправьте save и выполните весь трюк mergeChangesFromContextDidSaveNotification: с основным контекстом (скорее всего, он работает в основном потоке, поэтому используйте сообщение performSelectorOnMainThread...).

По умолчанию объект, созданный и возвращаемый NSManagedObjectContext, автореализован. Если вы создали новый объект и хотите его отредактировать в листе формы, например, вы можете вызвать setRetainsRegisteredObjects: с YES в контекст управляемого объекта перед созданием объекта, чтобы он сохранялся на объекте, созданном до тех пор, пока вы не с этим. Помните, что не рекомендуется управлять жизненным циклом NSManagedObject s самостоятельно - вы должны позволить NSManagedObjectContext сделать это. Поэтому, имея это в виду, вам не нужно сохранять NSManagedObject. После операции сохранения он незарегистрирован контекстом и удаляется из памяти. На вашей стороне ничего не требуется.

Ответ на обновленную часть вопроса

Было бы лучше, если бы вы вернули NSManagedObjectID (используя [object objectID]) вместо самого объекта. Он позволяет безопасно удалять объект по контексту, и если нужен объект для дальнейшего редактирования или поиска данных (например, из других контекстов), они могут извлекать его из магазина отдельно.

Даже если вы не сохраняете контекст, вновь созданный объект есть, а затем вы можете решить, хотите ли вы сохранить объект или нет.

После сохранения с другой стороны, если контекст все еще существует, он может вернуть объект с заданным NSManagedObjectID в кеш памяти, не касаясь базы данных.

В еще одной руке;) в вашем случае вы можете в значительной степени безопасно вернуть объект, поскольку создание NSManagedObjectContext его все еще существует, поэтому объект все равно будет существовать, хотя он уже находится в пуле автозаполнения.