Cara menaikkan NSNumber

108

Bagaimana cara menaikkan NSNumber?

yaitu myNSNumber ++

TheLearner
sumber
2
Ingat: saat menggunakan NSNumber *, selalu periksa untuk melihat apakah tipe primitif sudah cukup.
WKS
1
Saya terkejut bahwa tidak ada jawaban yang menyediakan cara cepat / optimal untuk melakukan itu, karena hanya untuk meningkatkan nilai Anda perlu melakukan kueri, menggabungkan, dan membuat objek baru, jadi melakukan ini secara berulang dapat memakan waktu.
PetrV

Jawaban:

123

Pembaruan: FYI, saya pribadi lebih suka jawaban satu baris BoltClock dan DarkDusts. Mereka lebih ringkas, dan tidak memerlukan variabel tambahan.


Untuk menaikkan NSNumber, Anda harus mendapatkan nilainya, menambah itu, dan menyimpannya di yang baru NSNumber.

Misalnya, untuk NSNumbermemegang integer:

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

Atau untuk NSNumbermemegang nomor floating-point:

NSNumber *number = [NSNumber numberWithDouble:...];
double value = [number doubleValue];
number = [NSNumber numberWithDouble:value + 1.0];
Itai Ferber
sumber
62
Ini adalah alasan nomor satu saya membenci properti NSNumber di Core Data. NSNumber sangat tidak nyaman untuk mengerjakan dan mengerjakan matematika.
Christian Schlensker
sekali lagi NSNumber tidak berfungsi saat menginisialisasi dengan nol memberikan nilai sampah.
Jignesh B
maaf, apa ...kepanjangannya? Itu referensi pseudo-code kan? ...
XCode
@boulder_ruby Ini ...hanyalah placeholder untuk nomor apa pun yang Anda inginkan.
Itai Ferber
126

NSNumberobjek tidak bisa diubah; hal terbaik yang dapat Anda lakukan adalah mengambil nilai primitif, menaikkannya kemudian membungkus hasilnya ke dalam NSNumberobjeknya sendiri :

NSNumber *bNumber = [NSNumber numberWithInt:[aNumber intValue] + 1];
BoltClock
sumber
28
Bahasa modern: 1, Objective-C: 0.
devios1
77

Bagi siapa saja yang menggunakan Xcode versi terbaru (menulis ini sebagai 4.4.1, SDK 5.1), dengan penggunaan literal objek, Anda dapat membersihkan kode bahkan sedikit lagi ...

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

Masih agak menyebalkan untuk berurusan dengan tinju dan membuka kotak segalanya untuk melakukan operasi sederhana, tetapi itu menjadi lebih baik, atau setidaknya lebih pendek.

shortstuffsushi
sumber
6
@softRli Lihat clang.llvm.org/docs/ObjectiveCLiterals.html untuk melihat lebih banyak ObjC Literals! Imo yang sangat berguna.
chown
1
Dan dalam hal ini Anda dapat menggunakan x - @ (x.intValue + 1), meskipun banyak orang tidak suka menggunakan notasi titik untuk memanggil metode non-properti. Ini lebih pendek, tetapi bisa disebut penyalahgunaan notasi titik.
Duncan C
@boulder_ruby, ini adalah penugasan ulang. NSNumbers tidak dapat diubah, jadi untuk "menaikkan" nilainya, Anda benar-benar harus menetapkannya kembali ke nilai yang baru.
shortstuffsushi
30

NSNumbers tidak dapat diubah, Anda harus membuat instance baru.

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

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

Gabungkan semuanya, dan Anda memiliki:

myNSNumber = @(myNSNumber.intValue + 1);
JLundell
sumber
bukankah Anda menetapkan ulang nilai myNSNumber di sini? Saya pikir itu tidak diizinkan karena NSNumberobjek tidak dapat diubah (?)
boulder_ruby
1
Anda sedang membuat objek NSNumber baru. myNSNumber adalah pointer (NSNumber *), dan memiliki nilai baru setelah Anda selesai.
JLundell
3

Saya suka ekspresi titik karena lebih ringkas dan itulah mengapa IOS mendukungnya sejak awal:

myNSNumber = [NSNumber numberWithInt:myNSNumber.intValue + 1];
mendongkrak
sumber
notasi titik tidak sesuai dengan yang Anda pikirkan, dan mungkin terkadang lebih lambat (bisa jadi default ke "valueForKey:" jika tidak ada aksesor yang disintesis untuk "properti" (dalam kasus Anda intValue). intValue tidak pernah didefinisikan sebagai @property dari NSNumber.
Motti Shneor
2

Jika Anda menggunakannya untuk menyimpan nilai integral:

myNSNumber = @(myNSNumber.longLongValue + 1);

Untuk item floating point, jawaban singkatnya adalah sebagai berikut, tetapi itu ide yang buruk untuk melakukan ini, Anda akan kehilangan ketepatan dan jika Anda melakukan perbandingan apa pun nanti seperti [myNSNumber isEqual: @ (4.5)] Anda mungkin akan terkejut :

myNSNumber = @(myNSNumber.floatValue + 1);

Jika Anda perlu melakukan matematika pada bilangan floating point yang direpresentasikan sebagai objek di Objective-C (yaitu jika Anda perlu meletakkannya dalam array, kamus, dll.), Anda harus menggunakan NSDecimalNumber.

lms
sumber
Jika Anda ingin memberi suara negatif, sebaiknya Anda bersikap konstruktif dan menjelaskan alasannya.
lms
Jawaban Anda menyiratkan bahwa NSNumberlah yang menyebabkan pembulatan kesengsaraan. Itu tidak benar, NSNumber memiliki perilaku pembulatan yang sama dengan jenis skalar. Juga saran Anda untuk menggunakan NSDecimalNumbers cukup menjengkelkan. Di sana Anda menyiratkan bahwa itu diperlukan jika Anda membutuhkan objek warga negara pertama di onmbjective-c. Tapi tentu saja jumlah objek juga. NSDecimalNumbers memiliki presisi yang lebih tinggi, tetapi kesalahan pembulatan juga mungkin terjadi dengannya. Dan: op menanyakan tentang incrementing, jawaban Anda dengan aritmatika float dan ganda. Tetapi itu tidak memiliki kenaikan, karena mereka tidak memiliki penerus alami.
vikingosegundo
@vikingosegundo Ini mengubah NSNumber menjadi float yang menyebabkan hilangnya akurasi karena NSNumber menyimpan nomor secara abstrak di mana float adalah base2, jadi ini bukan kesalahan NSNumber, tetapi konversi bolak-balik. Dan NSDecimalNumbers akan tidak menyebabkan kesalahan pembulatan untuk Base10 aritmatika, dan mereka yang dirancang untuk aritmatika, membaca doc. OP bertanya tentang menaikkan NSNumber, dan saya memberinya jawaban yang benar dan dapat dibaca untuk kasus integral, dan juga memberikan jawaban untuk kasus floating point tetapi menyarankan untuk tidak melakukannya dan kemudian menindaklanjutinya dengan saran yang lebih baik.
lms
Sebuah instance dapat mewakili bilangan apa pun yang dapat diekspresikan sebagai mantissa x 10 eksponen di mana mantissa adalah bilangan bulat desimal yang panjangnya hingga 38 digit, dan eksponen adalah bilangan bulat antara -128 dan 127. Tidak semua bilangan dapat diekspresikan seperti ini. Juga OP meminta penambahan yang mudah. NSDecimalNumber tidak menyediakannya. dan tetap saja jawaban Anda menyiratkan bahwa Anda memerlukan NSDecimalNumbers di ruang objek. itu salah.
vikingosegundo
Sobat Saya mencoba untuk benar-benar membantu dengan jawaban saya, dan berpikir downvote itu karena saya melakukan sesuatu yang salah dan saya pikir saya mungkin belajar sesuatu yang baru. Saya bisa melihat sekarang bukan itu masalahnya. Komentar Anda tidak masuk akal dan saya sarankan Anda membaca uo tentang sistem bilangan karena sistem bilangan berbasis 10. (Re. Kutipan Anda) tidak akan menyebabkan kesalahan pembulatan untuk basis 10 angka, saya tidak mengatakan apa-apa tentang presisi, hanya akurasi, tetapi 128 desimal juga memiliki banyak presisi.
lms
0

Gunakan kategori untuk memudahkan penggunaan di masa mendatang. Ini ide dasarnya.

 - (void)incrementIntBy:(int)ammount {
      self = [NSNumber numberWithInt:(self.intValue + ammount)];
 }
nizx
sumber
Ugh. Kategori yang mengimplementasikan metode instance yang menggantikan self?!? Itu sangat buruk. Mengapa tidak menulis metode instance yang memiliki hasil non-void dari NSNumber yang dihasilkan.
Duncan C
NSNumber didefinisikan sebagai tidak dapat diubah, oleh karena itu metode kategori ini melanggar keabadian yang seharusnya (bahkan jika mengganti diri). Kategori yang didesain lebih baik akan menambahkan inisialisasi baru ke NSNumber, dalam bentuk: + numberByIncrementingAmounf: (int) jumlah;
Motti Shneor
0

Banyak sekali info bagus di jawaban pertanyaan ini. Saya menggunakan jawaban yang dipilih dalam kode saya dan berhasil. Kemudian saya mulai membaca sisa posting dan banyak menyederhanakan kodenya. Ini sedikit lebih sulit untuk dibaca jika Anda tidak terbiasa dengan perubahan pada notasi yang diperkenalkan di Xcode 5, tetapi jauh lebih bersih. Saya mungkin bisa membuatnya hanya satu baris, tapi kemudian agak terlalu sulit untuk memikirkan apa yang saya lakukan.

Saya menyimpan NSNumber dalam kamus dan saya ingin menambahnya. Saya mengerti, mengubahnya menjadi int, menaikkannya sambil mengubahnya menjadi NSNumber, lalu memasukkannya kembali ke kamus.

Kode Lama

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

Kode baru

NSNumber *correct = [scoringDictionary objectForKey:@"correct"];
scoringDictionary[@"correct"] = @(correct.intValue + 1);
JScarry
sumber