Недавно созданный NSManagedObject возвращает временный идентификатор объекта даже после сохранения

Очень простая ситуация. Не знаю, почему это вызывает проблему.

У меня есть представление, которое создает новый NSManagedObject в дочернем NSManagedObjectContext. Когда пользователь нажимает "сделано", он сохраняет дочерний контекст, затем он сохраняет родительский контекст, а затем отправляет уведомление с вновь созданным объектным идентификатором объекта. В главном контроллере представления я отвечаю на уведомление и пытаюсь получить вновь созданный объект с помощью existingObjectWithID:error:.

Проблема в том, что это не так, потому что objectID является временным (я получаю "Cocoa ошибка 133000" ). Сохранение двух контекстов безупречно: когда я перезагружаю приложение, я вижу записи, которые я создал. Но в то время, когда мне нужно получить ссылку на новый объект, он терпит неудачу.

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

Примечание. Я попытался использовать obtainPermanentIDsForObjects:error:, который работает, но постоянный идентификатор все еще терпит неудачу, когда я пытаюсь использовать его для получения объекта.

Вот код:

-(IBAction)done:(id)sender
{
    if ([editorDoneNotification isEqualToString:kNOTIFICATION_OBJECTADDED]) {
        // save the temporary moc
        NSError* e;
        if (![self.tempContext save:&e]) { // this is always a successful save
            NSLog(@"Failed to save temporary managed object context: %@", [e localizedDescription]);
            [[[UIAlertView alloc] initWithTitle:@"Database Error"
                                    message:@"Failed to add object."
                                   delegate:nil
                          cancelButtonTitle:@"OK"
                          otherButtonTitles:nil] show];
        }
    }
    NSError* e;
    if (![[[AMDataModel sharedDataModel] mainContext] save:&e]) { // this is also successful
        NSLog(@"Failed to save main managed object context: %@", [e localizedDescription]);
        [[[UIAlertView alloc] initWithTitle:@"Database Error"
                                message:@"Failed to edit object."
                               delegate:nil
                      cancelButtonTitle:@"OK"
                      otherButtonTitles:nil] show];
    }
    else
        [[NSNotificationCenter defaultCenter] postNotificationName:editorDoneNotification object:[self.editingObject objectID]]; 

    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
}

И вот как я реагирую на уведомления:

-(void)objectAdded:(NSNotification*)notification
{
    if (self.popoverController && [self.popoverController isPopoverVisible]) {
        [self.popoverController dismissPopoverAnimated:YES];
    }

    NSManagedObjectID* newObjectID = (NSManagedObjectID*)(notification.object);
    NSError* error;
    AMObject* object = (AMObject*)[[[AMDataModel sharedDataModel] mainContext] existingObjectWithID:newObjectID error:&error]; // this is where the cocoa error 133000 happens
    if (error != nil) {
        NSLog(@"ERROR: Could not load new object in main managed object context.");
    }

    GMSMarker* m = [[GMSMarker alloc] init];
    m.position = CLLocationCoordinate2DMake(object.latitudeValue, object.longitudeValue);
    m.userData = object;
    m.map = self.mapView;
    [self.markers addObject:m];
}

-(void)objectEdited:(NSNotification *)notification
{  
    NSManagedObjectID* editedObjectID = (NSManagedObjectID*)notification.object;
    NSError* error = nil;
    AMObject* object = (AMObject*)[[[AMDataModel sharedDataModel] mainContext] existingObjectWithID:editedObjectID error:&error];
    if (error != nil) {
        NSLog(@"Error could not load edited object in main managed object context");
    }

    //update the UI based on edit

    if ([self.popoverController isPopoverVisible]) {
        [self.popoverController dismissPopoverAnimated:YES];
        self.popoverController = nil;
    }
}

Ответ 1

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

Обновление 1

Я не использую -objectID в этой ситуации. Он имеет некоторые виды использования, но не является постоянным уникальным идентификатором. В подобной ситуации я предпочитаю добавлять свой собственный уникальный идентификатор в объект, а затем извлекать его из основного контекста.

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

Ответ 2

Вы пытались получить постоянный идентификатор для своих объектов? У меня был успех обмена NSManagedObjectID между контекстами, вызывая

NSError *error = nil;
[self.context obtainPermanentIDsForObjects:@[object1, object2]
                                     error:&error];

затем мой метод сохранения. Я структурирую свои контексты таким образом, что есть контекст ввода-вывода, который является родителем для моего "контекста чтения" (контекста, используемого для моего основного потока), который является родителем для моих фоновых задач. Сохранение в этом случае распространяется по всей цепочке.