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];