除了在我的Core Data存储中为每个实体添加一个NSDate属性外,是否有一种程序化的方法来获取任何对象的修改日期?
没有,你必须自己添加一个日期并管理它。 您可以使用覆盖 -willSave
中更新时间戳,但请阅读NSManagedObject的API文档。-willSave
如何在更新时不引起willSave循环(文档中甚至提到了更新时间戳的情况)。 文档中还提到了在更新时间戳的情况下使用 NSManagedObjectContextWillSaveNotification
但这可能比简单的检查时间戳不要设置得太快更麻烦。
我个人会检查 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];
}
}
请注意,这个解决方案假设我们在模型中有一个叫做dateUpated的属性。
而不是在单个对象上处理这个问题。我会通过一个通知来处理这个问题。苹果文档也建议这样做。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willSaveContext:)
name:NSManagedObjectContextWillSaveNotification
object:nil];
- (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"];
}
}
}
我发现这个QA对开始在Core Data中设置修改日期的属性很有帮助。在这个过程中,我得出了几个小技巧,可能也会有帮助。
(技巧1:避免willSave递归)
commitEditing
和 save
后,循环。根本不用理会willSave。(提示2:实时更新--但对undo无效)
如果你需要实时更新,以便在表中向用户显示修改的日期,你也可以在你的objectValueForTableColumn委托方法(iOS的willDisplayCell)中为日期修改的列设置switch-case(或其他什么)中的dateModified。
在那里,测试该行的对象是否为Updated,如果是,则设置dateModified。我怀疑 if (obj isUpdated)
检查是非常昂贵的。但一定要只对相关的列进行检查,以免不必要的重复。
返回你对该列使用的任何字符串表示。为了避免实际修改的时间和设置的日期之间出现明显的差异,只显示日期,而不是时间。
这将导致每当用户进行表选择时,以及当表被重新加载时,dateModified都会被更新。这并不完美--如果用户修改了一个没有在表中显示的属性,那么在用户进行选择之前,该列不会更新。但这是合理的响应,比实现一个广泛的KVO方案要简单得多。
(你还是要在保存例程中设置日期,以捕捉对表不可见的修改。)
撤消复杂:不幸的是,撤消管理器会将表委托方法对dateModifed的修改视为一个事件本身。随后调用undo只是简单地撤销上次对dateModified的修改--一遍又一遍。我试着通过添加跟踪器和检查非空的 changedValues 字典来克服这个问题,以确保 dateModified 只在保存前设置一次。这对撤销删除有效,但对常规编辑无效。所以没有快速的方法来实现保存前dateModified的实时更新。