在不同情况下使用if语句的NSNumber

时间:2016-05-31 15:02:46

标签: objective-c if-statement nsnumber nsinteger

我知道要检查2个NSNumber是否与使用([A isEqualToNumber:B])而不是(A == B)相同,与NSIntegers不同。

但是,我刚刚意识到(A == B)在模拟器中工作正常,我想知道原因。

奇怪的是,在设备上,只要数字低于13,(A == B)仍然可以工作,从13开始它将停止工作,然后只有([A isEqualToNumber:B])工作但是如果它们大于12否则(A == B)仍然可以使用。

为什么?

3 个答案:

答案 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文字。不过,不要依赖它作为数字。