簡體   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