【问题标题】:Newly created NSManagedObject returns temporary objectID even after save即使保存后,新创建的 NSManagedObject 也会返回临时 objectID
【发布时间】:2013-08-26 22:55:33
【问题描述】:

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

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

问题是失败,因为 objectID 是临时的(我收到“Cocoa 错误 133000”)。这两个上下文的保存是完美的:当我重新加载应用程序时,我可以看到我创建的条目。但是当我需要获取对新对象的引用时,它失败了。

为什么它给我一个临时对象 ID 我已经保存了它?

注意:我尝试过使用obtainPermanentIDsForObjects:error:,它可以工作,但是当我尝试使用它来获取对象时,永久ID仍然失败。

这里有一些代码:

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

【问题讨论】:

    标签: ios objective-c core-data


    【解决方案1】:

    因为孩子没有从父 MOC 那里得到更新。父 MOC 将使用永久 ID 更新其自己的 NSManagedObject 实例,但该更改不会下推到属于子 MOC 的 NSManagedObject 实例。

    更新 1

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

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

    【讨论】:

    • 那么在这种情况下,在父 MOC 中获取对新创建对象的引用的最佳方法是什么?
    • 你使用什么标识符?
    • 我创建自己的全局唯一 ID 并将它们存储在对象中。
    【解决方案2】:

    您是否尝试过为您的对象获取永久 ID?我已经成功通过调用在上下文之间共享NSManagedObjectID's

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

    其次是我的保存方法。我以这样一种方式构建我的上下文,即有一个 I/O 上下文,它是我的“读取上下文”(用于我的主线程活动的上下文)的父级,它是我的后台任务上下文的父级。在这种情况下,保存会一直向上传播。

    【讨论】:

    • nil 传递给错误是一件坏事。它隐藏了让您摸不着头脑的错误。总是,总是,总是检查错误。
    • 100% 同意马库斯的观点——这是记忆中的快速 sn-p。为了完整起见,我进行了编辑。
    • 是的。我确实尝试过获得永久身份证(在我的问题中提到)。但是主上下文仍然无法获取对象。
    • 哦...我想我意识到我的错误:我在保存我的上下文之后调用obtainPermanentIDsForObjects:error: 。我也会尝试其他方式。
    • @MarcusSZarra: obtainPermanentIDsForObjects 就是这样做的。
    猜你喜欢
    • 1970-01-01
    • 2014-11-09
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    相关资源
    最近更新 更多