简体   繁体   English

NSNumber与if语句在不同情况下

[英]NSNumber with if statement in different situations

I know to check whether 2 NSNumbers are the same you need to use ([A isEqualToNumber:B]) instead of (A == B) unlike NSIntegers. 我知道要检查2个NSNumber是否与NSIntegers不同,需要使用([A isEqualToNumber:B])而不是(A == B)

However, I have just realized (A == B) works just fine in simulator and I'd like to know why. 但是,我刚刚意识到(A == B)在模拟器中可以正常工作,我想知道为什么。

The stranger thing is that on device, (A == B) STILL WORKS as long as the numbers are below 13 and from 13 it will stop working then only ([A isEqualToNumber:B]) works but that is if they're bigger than 12 otherwise (A == B) can still be used. 奇怪的是,在设备上, (A == B)仍然有效,只要数字在13以下,并且从13开始它将停止工作,然后只有([A isEqualToNumber:B])有效,但是如果它们更大大于12,否则(A == B)仍然可以使用。

Why's that?? 为什么??

It's an implementation detail. 这是一个实现细节。 The == compares the addresses of objects. ==比较对象的地址。 It just so happens that sometimes different object pointers are assigned to the same actual object when the content is the same and not mutable. 碰巧的是,当内容相同且不可更改时,有时会将不同的对象指针分配给同一实际对象。

Printing the pointer values is interesting: 打印指针值很有趣:

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 2016-05-31 11:30:49.118 TestApp [1542:3110206] 1-0x166539d0 2-0x166539d0 3-0x1656ac30 4-0x16587580

On NSNumber there are optimizations in work, because they are used very often. NSNumber有一些优化工作,因为它们经常被使用。

A. Twintones A.双音

The numbers from 0 to 12 are twintones (multitones). 从0到12的数字是双音(多音)。 12 is chosen, because hours and month indexes have this range. 之所以选择12,是因为小时和月份索引处于此范围内。 That means, that they are reused in every creation. 这意味着,它们可以在每个创建中重复使用。 In pseudo code (that would not work for many reasons): 在伪代码中(由于许多原因而无法使用):

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. Tagged Pointers B.标记指针

Numbers are sometimes stored as tagged pointers. 数字有时存储为标记指针。 The basic idea is that a pointer in a 64-bit environment on OS X is always aligned at 16 byte boundaries, making the least 4 bits always 0. 基本思想是,OS X上64位环境中的指针始终按16个字节边界对齐,从而使至少4位始终为0。

abc…xyz0000

The last bit is used to mark a tagged pointer. 最后一位用于标记标记的指针。 This three unused bits left of it can be used to mark a class instead of having a full isa (class) pointer. 剩下的这三个未使用位可用于标记类,而不是具有完整的isa(类)指针。 If you store, ie a 3 in it (binary 011) – or whatever – after a check you can say: "That's an instance of NSNumber storing an integer". 如果您在其中存储了3(二进制011)或其他内容,则可以在检查后说:“那是NSNumber存储整数的实例”。 The rest of the long word can be used to store the integer value. 长字的其余部分可用于存储整数值。 In such a case the pointer is the object, just encoded tricky. 在这种情况下,指针就是对象,只是编码比较棘手。 Two equal objects have the same "pointer", but it is no real pointer. 两个相等的对象具有相同的“指针”,但不是真正的指针。

But the most important thing: You should never take any advantage out of this optimizations. 但最重要的是:您永远都不应从这种优化中受益。 They are solely optimizations. 它们仅仅是优化。

There are great answers here already but note that there are other optimizations at work, for example: 这里已经有了不错的答案,但是请注意,还有其他优化工作,例如:

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

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

this will work for most numeric values because the literal values can be optimized already during compilation to result in exactly the same instance. 这将适用于大多数数值,因为文字值可以在编译过程中进行优化以得到完全相同的实例。

This (documented) optimization is often used to comparison of @YES AND @NO literals. 这种(已记录的)优化通常用于比较@YES@NO文字。 Don't rely on it for numbers though. 但是不要依靠它来获取数字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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