18

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

4

7 回答 7

24

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

于 2011-04-28T03:42:15.013 回答
12

我亲自检查是否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];
    }
}
于 2015-10-30T12:04:57.447 回答
9

在 WWDC19 上宣布了 Derived Attributes

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

核心派生属性截图

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

于 2020-06-11T15:33:44.143 回答
7

请注意,此解决方案假设我们在 model 中有一个名为 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"];
        }

    }

}
于 2015-03-04T15:36:32.077 回答
2

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

(提示 1:避免 willSave 递归)

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

(提示 2:实时更新——但不适用于撤消)

  • 如果您需要实时更新以在表格中向用户显示修改的日期,您还可以在您的 objectValueForTableColumn 委托方法(iOS 的 willDisplayCell)中为日期修改列在您的 switch-case(或其他)中设置 dateModified。

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

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

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

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

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

于 2011-12-18T21:51:57.977 回答
1

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

于 2015-09-03T08:38:09.013 回答
0

本·阿弗莱克答案的 Swift 版本

public override func willSave() {
    super.willSave()
        
    if !isDeleted, changedValues()["updatedAt"] == nil {
        self.setValue(Date(), forKey: "updatedAt")
    }
}
于 2021-04-05T17:13:30.423 回答