[英]NSNumber with if statement in different situations
我知道要检查2个NSNumber是否与NSIntegers不同,需要使用([A isEqualToNumber:B])
而不是(A == B)
。
但是,我刚刚意识到(A == B)
在模拟器中可以正常工作,我想知道为什么。
奇怪的是,在设备上, (A == B)
仍然有效,只要数字在13以下,并且从13开始它将停止工作,然后只有([A isEqualToNumber:B])
有效,但是如果它们更大大于12,否则(A == B)
仍然可以使用。
为什么??
这是一个实现细节。 ==
比较对象的地址。 碰巧的是,当内容相同且不可更改时,有时会将不同的对象指针分配给同一实际对象。
打印指针值很有趣:
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
在NSNumber
有一些优化工作,因为它们经常被使用。
A.双音
从0到12的数字是双音(多音)。 之所以选择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
存储整数的实例”。 长字的其余部分可用于存储整数值。 在这种情况下,指针就是对象,只是编码比较棘手。 两个相等的对象具有相同的“指针”,但不是真正的指针。
但最重要的是:您永远都不应从这种优化中受益。 它们仅仅是优化。
这里已经有了不错的答案,但是请注意,还有其他优化工作,例如:
NSNumber *x1 = @24;
NSNumber *x2 = @24;
NSLog(@"test: %@", x1 == x2 ? @"equal" : @"different"); // prints "equal"
NSLog(@"%p", x1);
NSLog(@"%p", x2);
这将适用于大多数数值,因为文字值可以在编译过程中进行优化以得到完全相同的实例。
这种(已记录的)优化通常用于比较@YES
和@NO
文字。 但是不要依靠它来获取数字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.