Недавно созданный 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];
затем мой метод сохранения. Я структурирую свои контексты таким образом, что есть контекст ввода-вывода, который является родителем для моего "контекста чтения" (контекста, используемого для моего основного потока), который является родителем для моих фоновых задач. Сохранение в этом случае распространяется по всей цепочке.