Objective c 核心数据-放弃更改

Objective c 核心数据-放弃更改,objective-c,core-data,model,Objective C,Core Data,Model,希望有人能解释发生了什么事 如果我从我的核心数据模型中得到一个对象,那么修改一个在模型中没有持久化甚至没有定义的属性!然后销毁并再次获取对象,该值仍与之前设置的值相同 为什么会这样 Promotion *promotion = [Promotion promotionWithId:[NSNumber numberWithInt:1512] inManagedObjectContext:context]; [promotion setQuantity:[NSNumber numberWit

希望有人能解释发生了什么事

如果我从我的核心数据模型中得到一个对象,那么修改一个在模型中没有持久化甚至没有定义的属性!然后销毁并再次获取对象,该值仍与之前设置的值相同

为什么会这样

Promotion *promotion = [Promotion promotionWithId:[NSNumber numberWithInt:1512] inManagedObjectContext:context];
    [promotion setQuantity:[NSNumber numberWithInt:2]];
    NSLog(@"%d", [promotion.quantity intValue]);
    promotion = nil;

    promotion = [Promotion promotionWithId:[NSNumber numberWithInt:1512] inManagedObjectContext:context];
    NSLog(@"%d", [promotion.quantity intValue]);
    promotion = nil;
输出为:

二, 二,

供参考:

+(Promotion *)promotionWithId:(NSNumber *)promotionId inManagedObjectContext:(NSManagedObjectContext *) context {
    NSFetchRequest *fetchReq = [[NSFetchRequest alloc]init];
    [fetchReq setEntity:[NSEntityDescription entityForName:@"Promotion" inManagedObjectContext:context]];

    NSPredicate *query = [NSPredicate predicateWithFormat:@"promotionId=%d", [promotionId intValue]];
    [fetchReq setPredicate:query];

    NSMutableArray *resultArray = [[NSMutableArray alloc]initWithArray:[context executeFetchRequest:fetchReq error:nil]];

    if([resultArray count] > 0) {
        return [resultArray objectAtIndex:0];
    }

    return nil;
}

核心数据缓存对象,缓存可能会保留未定义属性的IVAR


请尝试
[上下文刷新对象:升级合并更改:否]
然后执行log语句。

请记住,您对所有托管对象所做的更改将保留在Coredata的托管对象上下文中,直到您将其持久化(即保存上下文)

因此,在您的情况下,您正在对托管对象进行更改,将其引用设置为nil,但不重置上下文

这意味着您的更改仍然有效,下一次获取同一对象时将应用该更改

要完全摆脱它,您需要使用以下命令重置上下文:

[context reset];
从NSManagedObjectContext重置方法文档:

所有接收者的托管对象都被“遗忘”。如果您使用 方法时,您应该确保也放弃对任何 使用接收器获取的托管对象,因为它们将无效 后来


代码中有几个bug,我试图解释RestKit邮件列表中发生了什么。让我把答案粘贴在这里(加上一些更正,使文本更容易理解)


当然,托管对象上下文甚至不知道模型中未定义的属性,持久对象存储也不知道。因此,一定还有别的东西

让我们看看你的代码。您输入了
promotion=nil-不会释放对象。在代码的这一部分中,您没有泄漏,但在该阶段不会释放对象。该对象由resultArray持有

那么什么时候释放对象呢?它将与
resultArray
一起发布。您没有释放在
+promotionWithId:inManagedObjectContext:
中分配的
resultArray
。你根本没有释放它。似乎也没有理由首先将结果数组转换为可变数组

解决方案的两种变体:

NSArray *resultArray = [context executeFetchRequest:fetchReq error:nil];

这两个都是自动释放的对象。如果使用自动释放路径,则在最近的自动释放池排空或释放后,对象将立即释放。您可以通过将代码包装到以下位置来添加自动释放池: NSAutoreleasePool*池=[[NSAutoreleasePool alloc]init]; 和 [池释放]

如果没有这个,最近的自动释放池可能在Cocoa主运行循环中。因此,
resultArray
(以及由此产生的对象)将在Cocoa主运行循环中释放

您可能希望直接在
+promotionWithId:inManagedObjectContext:
中释放
resultArray
,但不能在保留和自动释放
[resultArray objectAtIndex:0]之前

那么,释放对象时会发生什么?希望它能从托管对象上下文中删除,任何获取的副本都应该是错误的(因为原始副本已经或应该已经消失)。坦率地说,我很惊讶对象的同一个副本一开始就被返回了(感谢你提出这个问题)——但这只是逻辑上的,因为核心数据只是一个对象图管理器,它方便地附带了一个高性能持久层

也可以手动将对象转换为故障:


希望这有帮助

谢谢你的回复,你的建议很有道理,但不幸的是没有效果。嗯。。。即使在处理核心数据将近一年之后,有时我还是不太明白。我唯一的其他想法是可能更改RetainRegisteredObjects属性。我假设重新启动应用程序时未保存该属性。我很想看看答案。如果我在没有设置数量的情况下重新启动应用程序,我会得到0,0。所以没有坚持。我已经把这个标记为正确的,因为它确实让我朝着正确的方向前进。重置就是这样。它重置了整个上下文,对我来说,这有点过分了。对我来说,回滚似乎更合适一些。
NSMutableArray *resultArray = [[NSMutableArray alloc] initWithArray:[context executeFetchRequest:fetchReq error:nil]];
[resultArray autorelease];