NSManagedObject 时间戳更新

Posted

技术标签:

【中文标题】NSManagedObject 时间戳更新【英文标题】:NSManagedObject timeStamp update 【发布时间】:2014-01-24 10:22:19 【问题描述】:

我想跟踪 NSManagedObject 属性的变化,以使 NSData *lastUpdate 属性保持“最新”

有几种方法可以在 NSManagedObject 更改其属性时获得通知

我。首先是覆盖所有要跟踪的属性的 setter 方法。这在 NSManaged 对象中相当复杂 - 检查它here

二。第二个可能是一个很好的。您可以覆盖在每次属性更改时调用的“didChangeValueForKey”方法。

-(void)didChangeValueForKey:(NSString *)key
    [super didChangeValueForKey:key];
    NSLog(@"Value for key:%@ has changed", key);

不幸的是,我们不应该重写这个方法,因为文档说...:

“你不能重写这个方法。”

三。键值观察让我们回到 IInd 方法,覆盖“didChangeValueForKey”。

更新。 四。我试图覆盖 -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)。

【问题讨论】:

您要跟踪什么,为什么?这决定了适当的方式来做到这一点...... 我必须跟踪 NSManaged 对象的 lastUpdate 【参考方案1】:

适合您的用例的解决方案是覆盖willSave 方法并使用它来设置新的lastUpdated 值。在将脏对象保存到上下文之前,会自动调用此方法。


如果您需要验证什么是脏的,您可以使用changedValues 属性的内容。

【讨论】:

不错,但如果我不想处理其中一项属性更改怎么办? 您可以检查 changedValues NSDictionary 并在这种情况下跳过更新时间戳。 如果您这样做,您可能希望使用setPrimitiveValue 方法来避免此更改触发另一个willChange 根据Apple 的文档调用:developer.apple.com/library/mac/Documentation/Cocoa/Reference/…【参考方案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 属性,否则您必须检查对象的类。

【讨论】:

【参考方案3】:

为了避免无限循环,试试这个魔法:

- (void)willSave
    if(![self.changedValues objectForKey:@"localModificationDate"])
        self.localModificationDate = [NSDate date];
    
    else
        [super willSave];
    

一旦设置了修改日期,它将不会为当前保存再次设置它。有一个副作用,如果保存失败并且您再次成功保存,我认为日期将是上次保存尝试的日期。

如果您在每次编辑后保存上下文,这很好,但核心数据的通常设计是仅在应用挂起或长时间后保存。所以很可能在此之前某些东西需要 lastUpdate 并且它还没有新的值。

【讨论】:

以上是关于NSManagedObject 时间戳更新的主要内容,如果未能解决你的问题,请参考以下文章

获取核心数据中 NSManagedObject 的修改日期?

根据时间戳选择并用零更新时间戳

使用 touch() 更新 laravel 中自定义时间戳字段的时间戳

如何将 MySql 时间戳列更新为 PHP 上的当前时间戳?

更新条目而不更新时间戳

时间戳(自动)何时更新?