在我的应用中,我在比较两个NSNumber
对象时意外地使用了“==”:
NSNumber *number1;
NSNumber *number2;
稍后,在设置了这些对象的int
值后,我意外地执行了此操作:
if (number1 == number2) {
NSLog(@"THEY'RE EQUAL");
}
令人困惑的是,它有效!我可以发誓我被教导这样做:
if (number1.intValue == number2.intValue) {
NSLog(@"THEY'RE EQUAL");
}
两个NSNumber
对象之间使用“==”的工作原理是什么?为什么?这是否意味着可以通过这种方式对它们进行比较,还是只是一个侥幸,这通常不能保证每次都有效?这让我很困惑:(
答案 0 :(得分:10)
这不是侥幸。 这是由于使用ARM64 CPU时Objective-C运行时的标记指针功能。
在Mac OS X 10.7中,Apple引入了标记指针。标记指针允许具有少量每实例数据的某些类完全存储在指针内。这可以消除对NSNumber等类的许多用途的内存分配的需要,并且可以提高性能。在ARM64上,Objective-C运行时包括标记指针,它们带来了所有相同的好处到了Mac
答案 1 :(得分:6)
这可能是侥幸。
来自NSHipster:
如果两个对象共享一组共同的可观察属性,则它们可能彼此相等或相等。然而,这两个对象仍然可以被认为是不同的,每个对象都有自己的身份。在编程中,对象的标识与其内存地址相关联。
您的语句可能会评估为YES
,因为number1
和number2
指向同一个对象。如果它们具有相同的值但是是两个不同的对象,则无效。
NSNumber
变量指向相同的明显原因是你明确地将一个变量指定给另一个,如下所示:
number1 = number2;
但是还有一个的东西。来自this answer:
这可能是编译器优化或实现细节:因为NSNumber是不可变的,所以不需要它们是单独的实例。可能是一个实现优化思考它。当随后使用相同的整数调用时,numberWithInt会返回一个单例。
但无论如何,使用isEqualToNumber:
是最安全的,因为没有人知道其他“的东西”潜藏在代码的深处,可能会也可能不会导致它评估{ {1}}
来自RyPress:
虽然可以直接比较NSNumber指针,但isEqualToNumber:方法是检查相等性的更强大的方法。它保证两个值相等,即使它们存储在不同的对象中。
答案 2 :(得分:2)
这里有两个平等概念:
在这种情况下,您希望值相等。在您的代码中,您声明了两个指向NSNumber
对象的指针:
NSNumber *number1;
NSNumber *number2;
但是在任何时候都没有显示给他们赋值。这意味着指针的内容可以是任何东西,并且很可能你有两个指针指向内存位置(不一定是相同的)(number1.intValue == number2.intValue)
恰好是真的。
您可以预期行为会以不稳定的方式更改 - 例如,只要您添加更多代码即可。
答案 3 :(得分:2)
当然你可以比较两个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])&#34 ;;这很好(没有检查我的名字是否正确)。