2012-09-11 19 views
6

Bardzo podoba mi się nowe literały w Objective-C. Zastanawiam się, czy z nowymi dodatkami jest lepszy sposób porównywania liczb.Porównanie literałów NSNumber

Na przykład, jeśli chcesz porównać a i b:

a = @1; 
b = @2; 

jest jedynym sposobem, aby porównać je tak:

[a intValue] > [b intValue] 

Albo istnieją lepsze, bardziej eleganckie rozwiązania?

+0

Jeśli chcesz, możesz napisać metodę dodawania kategorii, taką jak '[a betterThan: b]' i '[a equalTo: b]' – pasawaya

+0

Jest możliwe, że ponowne pisanie operatorów przez operatorów będzie w końcu pojawiać się jako rozszerzenie tej liczby literałów składnia. '@ 1' już staje się' [NSNumber numberWithInt: 1] '- nie ma powodu, że' @ 1> @ 2' nie mógłby być dozwolony i przepisany jako '[@ 1 isGreaterThan: @ 2]' (no cóż, bez powodu oprócz możliwego zamieszania: "Dlaczego nie mogę tego zrobić? Jeśli (1> @ 2)"? "). –

+0

Tak, masz rację, to zabrałoby porównawcze wskaźniki niskiego poziomu ... ale zawsze można było zrobić coś takiego jak @ 1 @> = @ 2, a następnie zaimplementować greaterThanOrEqualTo w NSNumber, więc byłoby to przetłumaczone jako [@ 1 greaterThanOrEqualTo: @ 2] ... w ten sposób możesz zachować arytmetyczne wskaźniki, jak również porównania logiczne. – 0xSina

Odpowiedz

13

Dla kontroli równości, można użyć isEqualToNumber który sprawdza czy też zawartość id lub jest równa (z tym ostatnim użyciu compare):

if ([a isEqualToNumber:b])     // if a == b 

Nie pewny dlaczego one również nie wdrożyły wygodnych metod (i prawdopodobnie także: >= i <=), ponieważ poniższa metoda wydaje się być trochę niezgrabna.

Dla kontroli nierówności, wystarczy użyć compare bezpośrednio (można to zrobić także za równością jak widać od pierwszego poniżej):

if ([a compare:b] == NSOrderedSame)   // if (a == b) 
if ([a compare:b] == NSOrderedAscending) // if (a < b) 
if ([a compare:b] == NSOrderedDescending) // if (a > b) 

if ([a compare:b] != NSOrderedSame)   // if (a != b) 
if ([a compare:b] != NSOrderedAscending) // if (a >= b) 
if ([a compare:b] != NSOrderedSescending) // if (a <= b) 

Szczegóły można znaleźć na NSNumber class documentation page.


Pamiętaj, nic nie uniemożliwia tworzenie własnej pomocnika funkcji, które na przykład pozwalają kod jak:

if (nsnComp1 (a, ">=", b)) ... // returns true/false (yes/no) 

czyli

if (nsnComp2 (a, b) >= 0) ... // returns -1/0/+1 

chociaż jest mniej Objective-C i więcej C :-) To zależy od tego, czy twoja definicja "eleganckiego" jest związana przede wszystkim wydajnością czy czytelnością. To, czy preferujesz opcję intValue, to decyzja, którą musisz podjąć sam.

+0

Zbyt szybko dla mnie! : D – Zhang

+0

Cóż, prawdopodobnie tylko dodano 'isEqualToNumber:', ponieważ metody 'isEqualTo ...' są używane w wielu innych miejscach [takich jak 'isEqualToString:']. Tylko IMHO. – Mazyod

+0

Dzięki ... nie wiedziałem o porównaniu, ale nadal nie wiesz> = lub <= .... byłoby bardziej niesamowicie, gdyby zrobili @ 1 == @ 2 ... ale rozumiem, dlaczego nie . – 0xSina

7

NSNumber implementuje -compare: (podobnie jak wiele innych klas). Więc można powiedzieć

switch ([a compare:b]) { 
    case NSOrderedAscending: // a < b 
     // blah blah 
     break; 
    case NSOrderedSame: // a == b 
     // blah blah 
     break; 
    case NSOrderedDescending: // a > b 
     // blah blah 
     break; 
} 
0

NSNumber posiada również isEqualToNumber:

0

Oto fragment kodu, aby sprawdzić, który działa dobrze:

NSLog(@"%d", number1 == number2); 
NSLog(@"%d", [number1 isEqual:number2]); 
NSLog(@"%d", [number1 isEqualToNumber:number2]); 

Wyjście:

1 
1 
1 

Wniosek:

Aby zrozumieć porównanie, należy zrozumieć alokację instancji.NSNumber wewnętrznie implementuje pamięć podręczną przypisanych obiektów i mapuje istniejące obiekty do wszystkich nowo utworzonych obiektów za pomocą wartości. Jeśli istniejący obiekt NSNumber zostanie znaleziony jako wartość 1, nie zostanie utworzona żadna nowa instancja NSNumber.