iOS – 为什么当我比较两个NSNumbers与“==”?

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

 NSNumber *number1; NSNumber *number2; 

后来,这些对象的int值被设置后,我不小心做到了这一点:

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

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

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

两个NSNumber对象之间如何使用“==”,为什么? 这是不是意味着可以这样比较呢,还是只是一种侥幸呢,一般不保证每次都能工作? 这真的让我困惑:(

这可能是一种侥幸。

来自NSHipster :

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

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

NSNumbervariables指向相同的显而易见的原因是你明确地将一个指派给另一个,如下所示:

 number1 = number2; 

但还有一件事 。 从这个答案 :

这可能是编译器优化或实现细节:由于NSNumber是不可变的,所以不需要它们是单独的实例。 可能是一个实现优化的思考。 可能numberWithInt返回一个单身人士,随后调用相同的整数。

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

Ry出版社 :

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

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

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

资源

这里有两个平等的概念:

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

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

 NSNumber *number1; NSNumber *number2; 

但是从来没有表明给他们分配一个价值。 这意味着指针的内容可以是任何东西,相当偶然的情况下,你有两个指向内存位置的指针(不一定是相同的),其中(number1.intValue == number2.intValue)碰巧是真的。

您可以期望行为以不稳定的方式改变 – 例如只要添加更多的代码即可。

当然,你可以比较两个NSNumber *与==。 这会告诉你指针是否相等。 当然,如果指针相等,那么值必须相同。 没有指针是相等的,值可以是相同的。

现在您需要知道,MaxOS X和iOS会进行一些重要的优化来节省存储空间,特别是在64位代码中。 许多代表相同整数值的NSNumber实际上是相同的指针。

 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])”; 没关系(没有检查我的名字是否正确)。