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

Posted

技术标签:

【中文标题】获取核心数据中 NSManagedObject 的修改日期?【英文标题】:Get modification date for NSManagedObject in Core Data? 【发布时间】:2011-08-14 08:58:04 【问题描述】:

除了向我的核心数据存储中的每个实体添加 NSDate 属性之外,是否有一种编程方式来获取任何对象的修改日期?

【问题讨论】:

【参考方案1】:

不,您必须添加日期并自行管理。您可以在托管对象中使用覆盖-willSave 来更新时间戳,但请阅读-willSave 上 NSManagedObject 的 API 文档,了解如何在不导致 willSave 循环的情况下进行更新(文档甚至讨论了更新时间戳的情况) .文档还提到使用NSManagedObjectContextWillSaveNotification,但这可能比简单的检查设置时间戳更麻烦。

【讨论】:

Apple 提供了如何执行此操作的示例。阅读 -willSave:developer.apple.com/library/mac/#documentation/Cocoa/Reference/… 这里是更新的链接:developer.apple.com/documentation/coredata/nsmanagedobject/…【参考方案2】:

我亲自检查updatedAt 是否被修改,如果是,我不再碰它。这样我就打破了willSave 循环。

- (void)awakeFromInsert 
    [super awakeFromInsert];

    self.primitiveUpdatedAt = [NSDate date];


- (void)willSave 
    [super willSave];

    if(![self isDeleted] && self.changedValues[@"updatedAt"] == nil) 
        self.updatedAt = [NSDate date];
    

【讨论】:

【参考方案3】:

在 WWDC19 上是 announced Derived Attributes。

像这样的updated 属性由Core Data 自动更新:

注意:这可能会产生无效的Mapping Model。

【讨论】:

好消息!非常感谢!【参考方案4】:

请注意,此解决方案假设我们有一个名为 dateUpated 的属性 在模型中。

而不是在单个对象上处理这个。我会通过通知处理这个问题。 Apple 文档也建议采用这种方式。

1。注册 NSManagedObjectContextWillSaveNotification 通知

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(willSaveContext:)         
                                             name:NSManagedObjectContextWillSaveNotification 
                                           object:nil];

2 为每个更新的对象在观察者方法中设置 updatedDate 的属性。

- (void)willSaveContext:(NSNotification *)notification

    NSManagedObjectContext *context = [notification object];
    NSSet *updatedObject = [context updatedObjects];

    for (NSManagedObject *managedObject in [updatedObject allObjects]) 
        if ([[managedObject.entity propertiesByName] objectForKey:@"dateUpdated"]) 
            [managedObject setValue:[NSDate date] forKey:@"dateUpdated"];
        

    


【讨论】:

【参考方案5】:

我发现此 Q/A 有助于开始为 Core Data 中的修改日期设置属性。在此过程中,我得出了一些可能也有帮助的提示:

(提示 1:避免 willSave 递归)

另一种避免 willSave 循环的方法是编写一个自定义例程来保存上下文,该例程遍历其 updatedObjects 查找具有 dateModified 属性的对象并进行设置。在该循环之后对commitEditingsave 进行实际调用。根本不用为 willSave 烦恼。

(提示 2:实时更新 - 但无法使用撤消)

如果您需要实时更新以在表格中向用户显示修改日期,您还可以在您的 objectValueForTableColumn 委托方法( ios 的 willDisplayCell)。

在那里,测试该行的对象是否已更新,如果是,则设置 dateModified。我怀疑if (obj isUpdated) 支票非常昂贵。但请务必仅针对相关列执行此操作,以免不必要地重复。

返回用于列的任何字符串表示形式。为避免实际修改的时间与设置的日期之间出现明显差异,请仅显示日期,而不是时间。

这将导致 dateModified 在用户进行表格选择以及重新加载表格时更新。这并不完美——如果用户修改了表中未表示的属性,则在他们做出选择之前,该列不会更新。但它比实施广泛的 KVO 方案响应迅速且容易得多。

(您仍需要在保存例程中设置日期,以捕获对表不可见的修改。)

UNDO 复杂性:不幸的是,撤消管理器会将表委托方法对 dateModifed 的更改视为其自身的事件。 随后调用 undo 只是一次又一次地撤消对 dateModified 的最后更改。我尝试通过添加一个跟踪器并检查一个非空的 changedValues 字典来克服这个问题,以确保 dateModified 仅在预保存时设置一次。这适用于撤消删除,但不适用于常规编辑。所以没有快速的方法来完成 dateModified 预保存的实时更新。

【讨论】:

提示 0:Apple 在文档中讲述了如何避免 willSave 递归。 developer.apple.com/library/mac/#documentation/Cocoa/Reference/…【参考方案6】:

如果有人想在 Swift 中以简单的方式做到这一点:我写了 a blog post 一个简单的 UpdateListener 类来更新所有 updateDateinsertDate 属性。您可以在this gist 中找到整个课程。您所要做的就是在您的应用程序委托的application(:didFinishLaunchingWithOptions:) 方法中调用UpdateListener.setupSharedInstance()

【讨论】:

【参考方案7】:

Ben Affleck 答案的 Swift 版本

public override func willSave() 
    super.willSave()
        
    if !isDeleted, changedValues()["updatedAt"] == nil 
        self.setValue(Date(), forKey: "updatedAt")
    

【讨论】:

以上是关于获取核心数据中 NSManagedObject 的修改日期?的主要内容,如果未能解决你的问题,请参考以下文章

核心数据。对大尺寸 NSManagedObject 的 NSMutableSet 进行排序

核心数据 - NSManagedObject(有关系)到 JSON

从众多实体中恢复一个获取的实体——核心数据

核心数据 - NSManagedObject 返回 nil

核心数据 NSManagedObject 更改

在 NSManagedObject 类中获取和保存数据的函数