我知道要检查2个NSNumber是否与使用([A isEqualToNumber:B])
而不是(A == B)
相同,与NSIntegers不同。
但是,我刚刚意识到(A == B)
在模拟器中工作正常,我想知道原因。
奇怪的是,在设备上,只要数字低于13,(A == B)
仍然可以工作,从13开始它将停止工作,然后只有([A isEqualToNumber:B])
工作但是如果它们大于12否则(A == B)
仍然可以使用。
为什么?
答案 0 :(得分:3)
这是一个实现细节。 ==
比较对象的地址。碰巧的是,当内容相同且不可变时,有时会将不同的对象指针分配给同一个实际对象。
打印指针值非常有趣:
NSNumber *n1a = [NSNumber numberWithInt:1];
NSNumber *n1b = [NSNumber numberWithInt:1];
if (n1a == n1b) {
NSLog(@"Match for 1");
}
NSNumber *n2a = [NSNumber numberWithInt:14];
NSNumber *n2b = [NSNumber numberWithInt:14];
if (n2a == n2b) {
NSLog(@"Match for 14");
}
NSLog(@"1-%p 2-%p 3-%p 4-%p", n1a, n1b, n2a, n2b);
2016-05-31 11:30:49.118 TestApp [1542:3110206] 1-0x166539d0 2-0x166539d0 3-0x1656ac30 4-0x16587580
答案 1 :(得分:3)
在NSNumber
上有优化工作,因为它们经常被使用。
一个。 Twintones
从0到12的数字是twintones(multitones)。选择12,因为小时和月份索引具有此范围。这意味着,它们会在每次创作中重复使用。在伪代码中(由于许多原因不起作用):
id twintones[13];
+ (instancetype)newWithInteger:(int)value
{
if(value>=0 and value1=12)
{
if(!twintones[value])
{
twintone[value] = …; // Usual creation
}
return twintone[value];
}
// Usual creation
}
B中。标记指针
有时将数字存储为标记指针。基本思想是OS X上64位环境中的指针始终以16字节边界对齐,使得最少4位始终为0。
abc…xyz0000
最后一位用于标记标记指针。它剩下的三个未使用的位可用于标记类而不是具有完整的isa(类)指针。如果你存储,我。即一个3中(二进制011) - 或其他 - 在检查后你可以说:"这是NSNumber
存储整数"的实例。长字的其余部分可用于存储整数值。在这种情况下,指针是对象,只是编码棘手。两个相等的对象具有相同的"指针",但它不是真正的指针。
但最重要的是:你永远不应该从这种优化中获取任何优势。它们只是优化。
答案 2 :(得分:0)
这里有很好的答案,但请注意还有其他优化工作,例如:
NSNumber *x1 = @24;
NSNumber *x2 = @24;
NSLog(@"test: %@", x1 == x2 ? @"equal" : @"different"); // prints "equal"
NSLog(@"%p", x1);
NSLog(@"%p", x2);
这适用于大多数数值,因为在编译期间可以优化文字值以产生完全相同的实例。
此(文档化)优化通常用于比较@YES
和@NO
文字。不过,不要依赖它作为数字。