不同情况下带if语句的NSNumber

NSNumber with if statement in different situations

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

但是,我刚刚意识到 (A == B) 在模拟器中工作得很好,我想知道为什么。

奇怪的是,在设备上,只要数字低于 13,(A == B) 仍然有效,从 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 上有优化工作,因为它们经常使用。

一个。双色调

从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
}

乙。标记指针

数字有时存储为标记指针。基本思想是 OS X 上的 64 位环境中的指针始终在 16 字节边界对齐,使最少 4 位始终为 0。

abc…xyz0000

最后一位用于标记标记指针。它剩下的这三个未使用的位可以用来标记一个 class 而不是一个完整的 isa (class) 指针。如果你存储,我。 e.其中有一个 3(二进制 011)——或其他任何东西——检查后你可以说:"That's an instance of NSNumber storing an integer"。长字的其余部分可用于存储整数值。在这种情况下,指针 对象,只是编码很棘手。两个相等的对象有相同的"pointer",但它不是真正的指针。

但最重要的是:您永远不应该从这种优化中获益。它们只是优化。

这里已经有很好的答案,但请注意还有其他优化在起作用,例如:

NSNumber *x1 = @24;
NSNumber *x2 = @24;

NSLog(@"test: %@", x1 == x2 ? @"equal" : @"different"); // prints "equal"
NSLog(@"%p", x1);
NSLog(@"%p", x2);

这适用于大多数数值,因为在编译期间可以优化文字值以产生完全相同的实例。

这种(已记录的)优化通常用于比较 @YES@NO 文字。不过不要依赖它来获取数字。