我想跟踪NSManagedObject属性的更改,以保持NSData * lastUpdate属性“最新”
当NSManagedObject更改其属性时,有几种方法可以获得Notified
予。首先是覆盖要跟踪的所有属性的setter方法。这在NSManaged对象中非常复杂 - 请检查here
II。第二个可能是一个好的。您可以覆盖“didChangeValueForKey”方法,该方法在每次更改属性时都会调用。
-(void)didChangeValueForKey:(NSString *)key{
[super didChangeValueForKey:key];
NSLog(@"Value for key:%@ has changed", key);
}
不幸的是,由于文档说明了......:
,我们不应该覆盖此方法“你不能覆盖这种方法。”
III。键值观察引导我们回到IInd方法,重写“didChangeValueForKey”。
UPD。 IV。我试图覆盖-willSave方法
-(void)willSave{
NSArray *observedKeys = @[@"name", @"imageType"];
NSDictionary * changesALL = self.changedValues;
for (id key in changesALL){
if ([observedKeys containsObject:key]){
self.lastUpdate = [NSDate date];
NSLog(@"updated For key: %@", key);
}
}
}
这导致了不定式循环,文档中对此进行了描述。 (这里描述了正确的方法,所以我已经回答了这个问题)
如果要更新持久属性值,通常应在进行更改之前使用现有值测试任何新值的相等性>。如果使用标准访问器方法更改属性>值,Core Data将观察结果更改>通知,因此在保存对象的托管对象>上下文之前再次调用willSave。如果你继续修改willSave中的值,willSave将继续被称为>直到你的程序崩溃。
例如,如果您设置了上次修改的时间戳,则应检查是否>先前在同一个保存操作中设置了它,或者现有时间戳是否小于>当前时间的小增量。通常,最好为所有正在保存的对象计算时间戳>(例如,响应> NSManagedObjectContextWillSaveNotification)。
答案 0 :(得分:4)
适合您的用例的解决方案,以覆盖willSave
方法并使用它来设置新的lastUpdated
值。在将脏对象保存到上下文之前,会自动调用此方法。
如果您需要验证哪些是脏的,您可以使用changedValues
属性的内容。
答案 1 :(得分:2)
因此,毕竟我发现跟踪托管对象更改的最佳解决方案是注册NSManagedObjectContextWillSaveNotification,并在托管对象上下文中设置所有更新和插入对象的时间戳。注册的方法可能如下所示:
-(void)contextWillSave:(NSNotification *)notify
{
NSManagedObjectContext *context = [notify object];
NSDate *dateOfTheLastModification = [NSDate date];
for (NSManagedObject *obj in [context insertedObjects]) {
[obj setValue:dateOfTheLastModification forKey:@"lastUpdate"];
}
for (NSManagedObject *obj in [context updatedObjects]) {
[obj setValue:dateOfTheLastModification forKey:@"lastUpdate"];
}
}
这假定您的所有实体都具有lastModifiedDate属性,否则您必须检查对象的类。
答案 2 :(得分:1)
为了避免无限循环,试试这个魔法:
- (void)willSave{
if(![self.changedValues objectForKey:@"localModificationDate"]){
self.localModificationDate = [NSDate date];
}
else{
[super willSave];
}
}
一旦设置了修改日期,它就不会再为当前保存设置它。有一个副作用,如果保存失败并再次成功保存,我认为日期将是上一次保存尝试的日期。
如果您在每次编辑后保存上下文,这很好,但通常的核心数据设计只能在应用程序暂停或长时间后保存。因此,在此之前可能会需要lastUpdate,并且它还没有获得新值。