【问题标题】:iOS - Why Does It Work When I Compare Two NSNumbers With "=="?iOS - 为什么当我用“==”比较两个 NSNumber 时它会起作用?
【发布时间】:2015-12-05 11:04:25
【问题描述】:

在我的应用程序中,我在比较两个 NSNumber 对象时不小心使用了“==”,如下所示:

NSNumber *number1;
NSNumber *number2;

后来,在设置了这些对象的int 值后,我不小心这样做了:

if (number1 == number2) {
    NSLog(@"THEY'RE EQUAL");
}

而且,令人困惑的是,它起作用了!我可以发誓我被教导这样做:

if (number1.intValue == number2.intValue) {
    NSLog(@"THEY'RE EQUAL");
}

在两个NSNumber 对象之间使用“==”是如何工作的,为什么?这是否意味着可以以这种方式比较它们,还是只是侥幸,而且通常不能保证每次都有效?这真的让我很困惑:(

【问题讨论】:

  • 其实很多情况下“intValue”都会失败。例如,如果两个 NSNumber 都包含大整数,或者附近但不同的浮点数。

标签: ios objective-c compare nsnumber


【解决方案1】:

这不是侥幸。 这是由于使用 ARM64 CPU 时 Objective-C 运行时的标记指针特性。

在 Mac OS X 10.7 中,Apple 引入了标记指针。标记指针允许将具有少量每个实例数据的某些类完全存储在指针中。这可以消除对 NSNumber 等类的许多用途的内存分配需求,并且可以提高性能。[...] 在 ARM64 上,Objective-C 运行时包括标记指针,具有它们带来的所有相同好处到 Mac

Source

【讨论】:

    【解决方案2】:

    这可能是侥幸。

    来自NSHipster

    如果两个对象共享一组共同的可观察属性,则它们可能彼此相等或等价。然而,这两个对象可能仍然被认为是不同的,每个对象都有自己的身份。在编程中,对象的身份与其内存地址相关联。

    您的语句评估为YES 可能是因为number1number2 指向同一个对象。如果它们具有相同的值但是两个不同的对象,这将不起作用。

    NSNumber 变量指向相同的明显原因是您明确地将一个分配给另一个,如下所示:

    number1 = number2;
    

    但还有另一件事。来自this answer

    这可能是编译器优化或实现细节:由于 NSNumber 是不可变的,因此不需要它们是单独的实例。可能是考虑它的实现优化。当随后使用相同的整数调用 numberWithInt 时,可能会返回一个单例。

    但无论如何,使用isEqualToNumber: 是最安全的,因为不知道还有哪些其他“事物”潜伏在代码的深处,可能会或可能不会导致它评估 YES

    来自RyPress

    虽然可以直接比较 NSNumber 指针,但 isEqualToNumber: 方法是一种更可靠的检查相等性的方法。它保证两个值比较相等,即使它们存储在不同的对象中。

    【讨论】:

    • 我在这里读到 (toptal.com/ios/interview-questions)(只需 control-f 搜索“==”,您就会找到问题和答案)iOS 编译器经过优化,可以在内存中设置相同的地址两个NSStrings 共享相同的值。 NSNumber 可能同样适用?
    • 是的,但我认为这不适用于NSNumber。我会检查并回复你。
    • 嗯,所以如果我有“朋友”对象,其中每个人的NSNumber“标识符”属性将始终被分配并引用为intValue,我总是可以使用“=”进行比较="?
    • @Rafi 更新了我的答案。该死!直到现在我才知道所有这些事情。所以谢谢你的问题。
    • 没问题,感谢您提供非常详细和引用的答案!
    【解决方案3】:

    这里有两个平等的概念:

    • 对象标识:比较两个指针指向相同的对象
    • 值相等:即两个对象的内容相等。

    在这种情况下,您需要值相等。在您的代码中,您声明了两个指向 NSNumber 对象的指针:

    NSNumber *number1;
    NSNumber *number2;
    

    但绝不会显示为它们分配值。这意味着指针的内容可以是任何内容,并且很可能您有两个指针指向 (number1.intValue == number2.intValue) 恰好为真的内存位置(不一定相同)。

    您可以预期行为会以不稳定的方式发生变化 - 例如,只要您添加更多代码。

    【讨论】:

    • 请注意,在 ARC 下,未初始化的对象指针值明确定义的:它们是 nil
    【解决方案4】:

    当然,您可以将两个 NSNumber* 与 == 进行比较。这将告诉您指针是否相等。当然,如果指针相等,则值必须相同。在指针不相等的情况下,值可以相同。

    现在您需要注意,MaxOS X 和 iOS 进行了一些重要的优化以节省存储空间,尤其是在 64 位代码中。许多表示相同整数值的 NSNumbers 实际上是相同的指针。

    NSNumber* value1 = [[NSNumber alloc] initWithInteger:1];
    NSNumber* value2 = [[NSNumber alloc] initWithInteger:1];
    

    这些将是 相同的 指针。在 64 位中,许多其他的将是相同的指针。只有两个具有布尔值的 NSNumber 对象。只有一个空的 NSArray 对象,并且只有一个 [NSNull null] 对象。

    不要让你陷入任何错误的假设。如果要查看两个 NSNumber 是否具有相同的值,请使用 isEqualToNumber:您可以说“if (number1 == number2 || [number1 isEqualToNumber:number2])”;没关系(没有检查我的名字是否正确)。

    【讨论】:

      猜你喜欢
      • 2022-06-19
      • 2023-03-22
      • 2016-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多