繁体   English   中英

NSNumber与if语句在不同情况下

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM