【问题标题】:Difference between dot syntax and valueForKey点语法和 valueForKey 的区别
【发布时间】:2012-07-14 08:31:20
【问题描述】:

请注意,更新 3 可能是最相关的

我正在使用 setValue:forKey: 设置带有 nsdate 对象的托管对象的 NSTimeInterval 属性

当我尝试获取值时,我得到了奇怪的东西,在运行时这个

NSLog(@"[managedObject valueForKey:@\"startTime\"] : %@, [NSDate dateWithTimeIntervalSince1970:[managedObject startTime]]: %@",
[managedObject valueForKey:@"startTime"],[NSDate dateWithTimeIntervalSince1970:[managedObject startTime]]);

返回

[managedObject valueForKey:@"startTime"] : 2012-07-14 08:13:05 +0000,
[NSDate dateWithTimeIntervalSince1970:[managedObject startTime]]: 1981-07-14 08:13:05 +0000

更新 1
[managedObject valueForKey:@"startTime"] 返回的值是正确的。不过我更喜欢使用[NSDate dateWithTimeIntervalSince1970:[managedObject startTime]] 或类似的东西,这样它的类型就更强了。

我相信 [managedObject startTime] 返回的值不正确 => 363954111.000000 .
但是我用这样的东西设置它:

managedObject setValue:1342261311 forKey:@"startTime"

值得注意的是,我不确定这是否不正确,因为[managedObject valueForKey:@"startTime"] 返回了一个正确的 NSDate 对象。

更新 2
我已经记录了 KVC 和 . 语法返回的双精度值。

managedObject.startTime = 363954111.000000
valueForKey timeIntervalSince1970 = 1342261311.000000

更新 3
好的,我已经设置了一个测试,开始时间是这样设置的entity.startTime = [[NSDate dateWithTimeIntervalSince1970:1342261311] timeIntervalSince1970];,结束时间是这样设置的[entity setValue:[NSDate dateWithTimeIntervalSince1970:1342261311] forKey:@"endTime"];

当我将它们写入日志时,我得到了这个start = 1342261311.000000, end = 363954111.000000

似乎 NSDate 对象的解包不正确,有人见过吗?

【问题讨论】:

  • startTime 是什么类型:NSDate 还是 NSTimeIntervall?
  • 这是一个 NSTimeInterval 属性
  • 您在编辑中提到的代码[NSDate dateWithTimeIntervalSince1970:[managedObject startTime]],不会产生正确的值吗?您是否尝试过分解您的代码,即在将其交给dateWithTimeIntervalSince1970: 之前检查startTime 是否包含您期望的值?
  • 那么,也许这就是你应该努力追求的——当然只是一个建议。但恐怕我现在必须退出这个交易所 - 祝你寻找错误好运!

标签: objective-c ios core-data key-value-coding nstimeinterval


【解决方案1】:

这里的问题是valueForKey: 旨在与对象值一起使用,实际上它返回一个id

为方便起见,valueForKey: 将原始类型(例如整数和双精度数)包装在它们的 NSNumber 对应物中。

您看到两个不同值的原因是valueForKey: 返回一个id,它本质上是指向内存中恰好存储NSNumber 的位置的指针。然后,您的代码只需获取这个任意内存地址并以某种方式将其解释为双精度,然后从中构造一个 NSDate

另一方面,直接调用 startTime 访问器方法会直接返回 double

如果你想使用valueForKey:,你可以这样做来获得真正的价值:

NSTimeInterval tiv = [[managedObject valueForKey:@"startTime"] doubleValue];

然后从那里开始工作。

实际上我有点惊讶编译器没有发出警告。 Apple 最新的编译器已经非常擅长捕捉此类问题。

【讨论】:

  • 嗯,好吧,valueForKey 返回正确的日期时间,我更喜欢使用 managedObject.startTime 并从那里开始,所以如果我更改类,我会收到编译器警告。有什么想法吗?
  • 听起来这是一个完全不同的问题,值得自己进行一些研究。更多的上下文也会很有用(它应该与什么代码一起使用,你得到的警告等等)
  • 我试图发布我认为是问题根源的内容。我知道我没有在问题中正确解释问题,我已对其进行了编辑,并希望将其保留在这里。我没有收到任何警告,除了设置值的操作之外,没有太多的上下文可以提供。您还有其他想法吗?
【解决方案2】:

这是时代差异的问题。 NSDate 使用 2001 年 1 月 1 日作为纪元。因此,当我获得价值时,我使用的是 unix epoch (1970)。这让我在价值观上有所不同。

当 KVC 使用 NSDate 对象解包和包装 NSTimeInterval 时,它使用 NSDate 2001 纪元。

所以不要使用dateWithTimeIntervalSince1970 我在获取值时使用了dateWithTimeIntervalSinceReferenceDate

【讨论】:

    【解决方案3】:

    NSTimeInterval 是一个双精度类型

    typedef double NSTimeInterval;
    

    您不能将标量直接存储在核心数据中,但您必须将它们包装在 NSNumber 中,或者在您的情况下使用 NSDate 可能更容易。

    【讨论】:

    • 我在生成托管对象时选择了使用标量属性。问题不是,我可以使用它。这就是为什么我在不使用键值编码的情况下得到奇怪的结果
    【解决方案4】:

    如果 startTime 是一个 NSTimeInterval(而不是一个 NSDate),那么你正在比较两个不同的东西,一个双精度对象和一个 NSDAte 对象。

    [managedObject valueForKey:@"startTime"] 将返回一个 NSTimeInterval,一个原语(顺便说一下,您应该使用 %f 打印它)。

    [NSDate dateWithTimeIntervalSince1970:[managedObject startTime]] 会返回一个 NSDate。

    如果你真的想比较两者,你应该使用[NSDate dateWithTimeIntervalSince1970:[managedObject valueForKey:@"startTime"]] 来正确比较两个 NSDate 对象。

    【讨论】:

    • startTime 是一个 NSTimeInterval,但是使用 valueForKey 会返回一个 NSDate 的实例。当 managedObject.startDate 返回一个 NSTimeInterval 值时,这就是我在后者上使用 dateWithTimeIntervalSince1970 的原因。此外,当我使用 %f 时出现 badAccess 错误,强制执行 valueForKey 返回日期对象的事实。
    猜你喜欢
    • 2010-11-06
    • 2013-04-16
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-01
    • 2021-03-28
    • 1970-01-01
    相关资源
    最近更新 更多