即使保存后,新创建的NSManagedObject也会返回临时objectID [英] Newly created NSManagedObject returns temporary objectID even after save

查看:118
本文介绍了即使保存后,新创建的NSManagedObject也会返回临时objectID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

很简单的情况。不知道为什么会导致问题。

Very simple situation. Not sure why it's causing an issue.

我有一个视图,在一个子NSManagedObjectContext中创建一个新的NSManagedObject。当用户按完成时,它保存子上下文,然后保存父上下文,然后它使用新创建的对象的objectID发布通知。在主视图控制器中,我回应通知并尝试使用 existingObjectWithID:error:获得新创建的对象。

I have a view that creates a new NSManagedObject in a child NSManagedObjectContext. When the user presses "done", it saves the child context, then it saves the parent context, then it posts a notification with the newly created object's objectID. In the main view controller, I respond to the notification and try to get the newly created object with existingObjectWithID:error:.

问题是这失败,因为objectID是临时的(我得到一个Cocoa错误133000)。保存到这两个上下文是完美的:当我重新加载应用程序,我可以看到我创建的条目。

Problem is this fails because the objectID is temporary (I get a "Cocoa error 133000"). The saves to the two contexts are flawless: when I reload the app, I can see the entries I created. But at the time I need to get a reference to the new object, it fails.

为什么在之后给我一个临时对象ID 我已经保存了它。

Why does it give me a temporary object ID after I've already saved it?

注意:我尝试使用 getsPermanentIDsForObjects:error:在尝试使用永久ID获取对象时,永久ID仍然失败。

Note: I have tried using obtainPermanentIDsForObjects:error:, which works, but the permanent ID still fails when I try to use it to obtain the object.

以下是一些代码:

-(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;
    }
}


推荐答案

该子节点不会从父节点MOC更新回来。父MOC将使用永久ID更新其自己的 NSManagedObject 实例,但是该更改不会被下推到 NSManagedObject 属于子MOC。

Because the child does not get updated back from the parent MOC. The parent MOC will update its own instance of the NSManagedObject with a permanent ID but that change will not be pushed down to the instance of that NSManagedObject belonging to the child MOC.

我不使用 -objectID 。它有一些用途,但它不是永久唯一ID。在这样的情况下,我喜欢添加我自己的uniqueID到实体,然后从主上下文中提取它。

I do not use -objectID in this situation. It has some uses but it is not a permanent uniqueID. In a situation like this, I prefer to add my own uniqueID to the entity and then fetch it from the main context.

您也可以只监听上下文保存通知或使用将接收更新的NSFetchedResultsController。

You could also just listen for the context save notifications or use an NSFetchedResultsController which will receive updates.

这篇关于即使保存后,新创建的NSManagedObject也会返回临时objectID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆