NSNumber nasıl artırılır


108

NSNumber'ı nasıl artırabilirim?

yani myNSNumber ++


2
Unutmayın: kullanırken NSNumber *, her zaman ilkel türlerin yeterli olup olmayacağını kontrol edin.
WKS

1
Bunu yapmanın hızlı / optimize edilmiş bir yolunu sağlayan bir yanıt olmamasına şaşırdım, çünkü sadece değeri artırmak için yeni nesneyi sorgulamanız, birleştirmeniz ve yaratmanız gerekiyor, bu yüzden bunu döngü içinde yapmak zaman alıcı hale gelebilir.
PetrV

Yanıtlar:


123

Güncelleme: Bilginize, şahsen BoltClock ve DarkDusts'ın tek satırlık cevaplarını daha çok beğeniyorum. Daha özlüdürler ve ek değişkenler gerektirmezler.


An NSNumberdeğerini artırmak için değerini almanız, artırmanız ve yenisinde saklamanız gerekir NSNumber.

Örneğin, NSNumbertutan bir tam sayı için:

NSNumber *number = [NSNumber numberWithInt:...];
int value = [number intValue];
number = [NSNumber numberWithInt:value + 1];

Veya NSNumberbir kayan noktalı sayı tutmak için:

NSNumber *number = [NSNumber numberWithDouble:...];
double value = [number doubleValue];
number = [NSNumber numberWithDouble:value + 1.0];

62
Bu, Core Data'daki NSNumber özelliklerinden nefret etmemin bir numaralı nedenidir. NSNumber ile çalışmak ve matematik yapmak çok zahmetli.
Christian Schlensker

tekrar NSNumber sıfır ile başlatılırken çalışmadı, çöp değeri verir.
Jignesh B

pardon, ne anlama geliyor ...? Bu bir sözde kod referansı değil mi? XCode ...
do

@boulder_ruby ...İstediğiniz herhangi bir sayı için sadece bir yer tutucudur.
Itai Ferber

126

NSNumbernesneler değişmezdir; yapabileceğiniz en iyi şey, ilkel değeri kapmak, onu artırmak ve ardından sonucu kendi NSNumbernesnesine kaydırmaktır :

NSNumber *bNumber = [NSNumber numberWithInt:[aNumber intValue] + 1];

28
Modern diller: 1, Amaç-C: 0.
devios1

77

Xcode'un en son sürümünü kullanan herkes için (bunu 4.4.1, SDK 5.1'den itibaren yazıyor), nesne değişmezlerini kullanarak kodu biraz daha temizleyebilirsiniz ...

NSNumber *x = @(1);
x = @([x intValue] + 1);
// x = 2

Yine de basit operasyonlar yapmak için boks yapmak ve her şeyi kutudan çıkarmakla uğraşmak biraz acı verici, ama daha iyi ya da en azından kısalıyor.


6
@softRli Daha fazla ObjC Literatürü görmek için clang.llvm.org/docs/ObjectiveCLiterals.html adresine bakın! Çok kullanışlı imo.
chown

1
Ve bu konuda x - @ (x.intValue + 1) kullanabilirsiniz, ancak çoğu insan özellik dışı yöntemleri çağırmak için nokta notasyonu kullanmayı sevmez. Daha kısadır, ancak nokta gösteriminin kötüye kullanılması olarak adlandırılabilir.
Duncan C

@boulder_ruby, yeniden atamadır. NSNumber'lar değişmezdir, bu nedenle değeri "artırmak" için, aslında onu yeni bir değere yeniden atamanız gerekir.
shortstuffsushi

30

NSNumbers değişmez, yeni bir örnek oluşturmanız gerekir.

// Work with 64 bit to support very large values
myNSNumber = [NSNumber numberWithLongLong:[myNSNumber longLongValue] + 1];

// EDIT: With modern syntax:
myNSNumber = @([myNSNumber longLongValue] + 1);

24

Hepsini bir araya getirirseniz:

myNSNumber = @(myNSNumber.intValue + 1);

myNSNumber değerini burada yeniden atamıyor musunuz? NSNumberNesneler değişmez olduğu için buna izin verilmediğini düşündüm (?)
boulder_ruby

1
Yeni bir NSNumber nesnesi oluşturuyorsunuz. myNSNumber bir göstericidir (NSNumber *) ve işiniz bittiğinde yeni bir değer alır.
JLundell

3

Nokta ifadesini seviyorum çünkü daha kısa ve bu yüzden IOS ilk etapta onu destekliyor:

myNSNumber = [NSNumber numberWithInt:myNSNumber.intValue + 1];

nokta gösterimi düşündüğünüzü yapmıyor ve zaman zaman daha yavaş olabilir ("özellik" için sentezlenmiş erişimci yoksa (sizin durumunuzda intValue) "valueForKey:" varsayılan olabilir. intValue hiçbir zaman @ özellik olarak tanımlanmadı of NSNumber.
Motti Shneor

2

İntegral bir değer depolamak için kullanıyorsanız:

myNSNumber = @(myNSNumber.longLongValue + 1);

Kayan noktalı şeyler için kısa cevap şudur, ancak bunu yapmak kötü bir fikirdir, hassasiyeti kaybedersiniz ve daha sonra [myNSNumber isEqual: @ (4.5)] gibi herhangi bir karşılaştırma yaparsanız şaşırabilirsiniz :

myNSNumber = @(myNSNumber.floatValue + 1);

Objective-C'de nesneler olarak temsil edilen kayan nokta sayıları üzerinde matematik yapmanız gerekiyorsa (yani onları dizilere, sözlüklere vb. Koymanız gerekiyorsa) kullanmalısınız NSDecimalNumber.


Olumsuz oy vereceksen, yapıcı ol ve nedenini de söyleyebilirsin.
lms

Cevabınız, yuvarlanan sıkıntıları ortaya çıkaranın NSNumber olduğunu ima ediyor. Bu doğru değil, NSNumber skaler türlerle aynı yuvarlama davranışına sahiptir. Ayrıca NSDecimalNumbers kullanma tavsiyeniz oldukça rahatsız edici. Orada, hedef-c'de ilk yurttaş nesnelerine ihtiyacınız varsa, bunların gerekli olduğunu ima ediyorsunuz. Ama tabii ki nesnelere de nsnumber. NSDecimalNumbers daha yüksek bir hassasiyete sahiptir, ancak onlarla da yuvarlama hatası oluşabilir. Ve: op, artan, float ve double aritmetik ile cevabınızı sorar. Ancak doğal halefleri olmadığı için bunların artması yoktur.
vikingosegundo

@vikingosegundo Bir NSNumber, doğruluk kaybına neden olan bir kayan noktaya dönüştürülüyor çünkü NSNumber sayıları soyut olarak float'ın base2 olduğu yerde saklar, yani bu NSNumber'ın hatası değil, ileri geri dönüşümün hatası. Ve NSDecimalNumbers olacak değil neden aritmetik Base10 ilgili hataları yuvarlama ve bunlar vardır doc okumak, aritmetik için tasarlanmış. OP, bir NSNumber'ın artırılmasını istedi ve ben ona integral durum için doğru ve okunabilir bir cevap verdim ve ayrıca kayan nokta durumu için bir cevap verdim, ancak buna karşı tavsiyede bulunduktan sonra daha iyi bir öneriyi takip ettim.
lms

Bir örnek, mantis x 10 üssü olarak ifade edilebilen herhangi bir sayıyı temsil edebilir; burada mantis, 38 basamağa kadar ondalık bir tam sayıdır ve üs, -128 ile 127 arasında bir tamsayıdır. Her sayı bu şekilde ifade edilemez. Ayrıca OP, kolay artış istedi. NSDecimalNumber bunu sağlamaz. ve yine de cevabınız, nesne alanında NSDecimalNumber'a ihtiyacınız olduğunu ima ediyor. bu yanlış.
vikingosegundo

Dostum, cevabıma gerçekten yardımcı olmaya çalışıyordum ve olumsuz oylamanın bir şeyi yanlış yaptığım ve yeni bir şeyler öğrenebileceğimi düşündüğüm için olduğunu düşündüm. Durumun bu olmadığını şimdi anlıyorum. Yorumlarınız bir anlam ifade etmiyor ve sayı sistemlerini okumanızı öneririm çünkü 10 numaralı bir sistem. (Re. Senin alıntı) taban 10 sayılar için herhangi bir yuvarlama hatasına neden olmaz, kesinlik hakkında hiçbir şey söylemedim, sadece doğruluk, ama 128 ondalık da çok fazla hassasiyete sahip.
lms

0

İleride kullanımı kolaylaştırmak için bir kategori kullanın. İşte temel bir fikir.

 - (void)incrementIntBy:(int)ammount {
      self = [NSNumber numberWithInt:(self.intValue + ammount)];
 }

Ugh. Self?!? 'İn yerini alan bir örnek yöntemi uygulayan bir kategori Bu cidden iğrenç. Sonuçta ortaya çıkan NSNumber'ın geçersiz olmayan dönüşüne sahip bir örnek yöntemi neden yazmıyorsunuz?
Duncan C

NSNumber değişmez olarak tanımlanmıştır, bu nedenle bu kategori yöntemi varsayılan değişmezliğini ihlal etmektedir (kendini değiştirse bile). Daha iyi tasarlanmış bir kategori bunun yerine NSNumber'a şu biçimde yeni bir başlatıcı ekler: + numberByIncrementingAmounf: (int) miktar;
Motti Shneor

0

Bu sorunun yanıtlarında pek çok iyi bilgi var. Seçilen cevabı kodumda kullandım ve işe yaradı. Sonra geri kalan yazıları okumaya başladım ve kodu çok basitleştirdim. Xcode 5'te tanıtılan notasyondaki değişikliklere aşina değilseniz okumak biraz daha zordur, ancak çok daha temizdir. Muhtemelen tek bir satır yazabilirim, ama sonra ne yaptığımı anlamak biraz zor.

Bir sözlüğe bir NSNumber kaydediyorum ve onu artırmak istiyorum. Anladım, int'e dönüştürüyorum, NSNumber'a dönüştürürken artırıyorum, sonra sözlüğe geri koyuyorum.

Eski Kod

 NSNumber *correct = [scoringDictionary objectForKey:@"correct"];
 int correctValue = [correct intValue];
 correct = [NSNumber numberWithInt:correctValue + 1];
 [scoringDictionary removeObjectForKey:@"correct"];
 scoringDictionary[@"correct"] = correct;

Yeni kod

NSNumber *correct = [scoringDictionary objectForKey:@"correct"];
scoringDictionary[@"correct"] = @(correct.intValue + 1);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.