为啥核心数据托管对象中的 NSDate 转换为 NSTimeInterval?

Posted

技术标签:

【中文标题】为啥核心数据托管对象中的 NSDate 转换为 NSTimeInterval?【英文标题】:Why is an NSDate in a Core Data managed Object converted to NSTimeInterval?为什么核心数据托管对象中的 NSDate 转换为 NSTimeInterval? 【发布时间】:2011-07-27 08:39:31 【问题描述】:

我有一个对象,该对象的属性具有在我的 xcdatamodeld 对象中定义的 Date 类型。为什么它会生成带有 NSTimeInterval 的 NSManagedObject 类?以及如何在其上设置一个 NSDate ,然后从它那里获得一个 NSDate ?

【问题讨论】:

这很奇怪。它们应该是 NSDate 对象。您使用的是什么类型的商店? 【参考方案1】:

如果我在生成文件时选中“使用原始数据类型的标量属性”复选框,我会得到这个。

这是因为 NSTimeInterval 是变相的 double,而 NSDate 是继承自 NSObject 的类。

【讨论】:

答案是正确的,但推理对我来说毫无意义。 Objective-C 中的每个类都继承自 NSObject。问题是:为什么在选中“对原始数据类型使用标量属性”复选框生成 NSManagedObject 子类时,字符串属性会转换为 NSString 对象,而日期属性会转换为 NSInterval。顺便说一句,我会接受“在 Apple 工作的小精灵”作为答案。 @ElisevanLooij 与数字、日期和布尔值不同,字符串不能表示为标量属性,因此复选框不会影响字符串属性转换。二进制数据属性也一样。 如何创建一个 NSManagedObject 子类,以便同时存在一个 int 和一个 NSDate? @VictorPrograss 您可以手动编辑生成的实体并将NSTimerInterval 替换为NSDate*。还要在@property注解中添加retain 我不建议编辑生成的属性,因为如果你重新生成你的类,你会丢失这些编辑。【参考方案2】:

编辑:显然dateWithTimeIntervalSince1970 仅适用于NSDateFormatterNSDate 使用与 NSDateFormatter 不同的引用,正如 cmets 中所解释的,它是在 2001 年。 对不起,我的无知。

如果您在为实体生成NSManagedObject 子类时选择了“对原始数据类型使用标量属性”,它将使用标量属性,例如 int 和 float,而不是 NSNumber。这包括 NSDate;它会将NSDate 变成NSTimeInterval,这只是一个双倍。 NSTimeInterval 是自 Apple 使用的 1970 年标准纪元以来的时间间隔(如果是 1970 年之前,则可能为负数)。

如果您需要,将NSTimeInterval 转换回NSDate 非常简单,但如果您没有庞大的数据库,那么您可能不想费心选择该复选框。

要将此时间间隔转换为NSDate,只需使用[NSDate dateWithTimeIntervalSince1970: timeInterval];,其中timeInterval 是您从数据库中获得的信息。这可以放在您的NSManagedObject 子类中,这样当您获得该属性时,无论如何您都会获得NSDate

【讨论】:

这并不完全正确。文档状态: NSManagedObject 使用 NSDate 对象表示日期属性,并在内部将时间存储为自参考日期(其时区为 GMT)以来的 NSTimeInterval 值。参考日期 = 2001 年 1 月 1 日,而不是 1970 年 1 月 1 日 那为什么他们有函数“dateWithTimeIntervalSince1970”?另外,所以您是说使用原始存储量与不使用存储量没有区别? 您应该阅读 Apple 文档。我引用了这些文档中的文字。 NSDateFormatter 的参考日期是 1970 年 1 月 1 日。因此,dateWithTimeIntervalSince1970 在使用日期格式化程序时非常有用。但是,你可以问苹果为什么 NSDate 和 NSDateFormatter 有不同的参考日期。 哦,我明白了。感谢您的澄清。编辑了我的答案。【参考方案3】:

如果您希望拥有同时使用标量和非标量属性表示的混合实体,例如 int32_t 用于整数或布尔属性,而 NSDate* 用于日期属性,则需要手动编辑生成的托管对象 .h文件。

因此,我通常首先通过检查选项对原始数据类型使用标量属性来创建托管对象类(因为我有比日期更多的整数和布尔属性)。然后我编辑创建的头文件如下:

MYEntity.h

@interface MYEntity : NSManagedObject
@property (nonatomic) int32_t index;
@property (nonatomic) NSTimeInterval date;
@end

然后变成:

@interface MYEntity : NSManagedObject
@property (nonatomic) int32_t index;
@property (nonatomic, retain) NSDate * date;
@end

如果您不喜欢手动编辑此文件,您还可以选择使用允许像访问对象一样访问标量属性的类别添加便利属性。

MYEntity+Convenience.h:

@interface MYEntity (Convenience)
@property (nonatomic, readwrite) NSDate *theDate
@end

MYEntity+Convenience.h:

@implementation MYEntity (Convenience)

- (NSDate *)theDate 
    return [NSDate dateWithTimeIntervalSinceReferenceDate:self.date];


- (void)setTheDate:(NSDate *)theDate 
    self.date = [theDate timeIntervalSinceReferenceDate]


@end

为了使本示例中的代码更具可读性,我将在数据模型设计器中将原始属性命名为 dateTimeInterval,并将便利属性命名为所需的名称:date

显然第二种方法反之亦然。您可以导出具有非标量属性的实体,然后提供方便的标量属性,其 getter 和 setter 可以访问原始的非标量属性。

【讨论】:

以上是关于为啥核心数据托管对象中的 NSDate 转换为 NSTimeInterval?的主要内容,如果未能解决你的问题,请参考以下文章

如何快速将核心数据托管对象数组转换为“可识别”列表? (Xcode 11,测试版 5)

核心数据获取...为啥在将托管对象插入上下文 A 并保存上下文 A 后,不使用上下文 B 获取托管对象?

为啥Core Data会从我在NSDate的天数中减去1

核心数据:创建多个托管对象,但只保存一些?

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

核心数据保存日期错误