Як збільшити NSNumber


108

Як я збільшую NSNumber?

тобто myNSNumber ++


2
Пам'ятайте: під час використання NSNumber *завжди перевіряйте, чи вистачить примітивних типів.
WKS

1
Я здивований, що жодної відповіді, що забезпечує швидкий / оптимізований спосіб зробити це, немає, тому що просто для збільшення значення потрібно запитувати, комбінувати та створювати новий об’єкт, тому робити це в циклі може зайняти багато часу.
ПетрВ

Відповіді:


123

Оновлення: FYI, мені особисто більше подобаються однорядкові відповіді BoltClock та DarkDusts. Вони більш стислі та не потребують додаткових змінних.


Для збільшення прибутку NSNumberвам доведеться отримати його значення, приріст і зберегти його в новому NSNumber.

Наприклад, для NSNumberпроведення цілого числа:

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

Або для NSNumberтримання номера з плаваючою комою:

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

62
Це причина номер один, що я ненавиджу властивості NSNumber в основних даних. NSNumber настільки незручно працювати і виконувати математику.
Крістіан Шленскер

знову NSNumber не працює під час ініціалізації з нульовим значенням сміття.
Jignesh B

Вибачте, що означає ...позиція? Це псевдо-код посилання правильно? XCode не...
boulder_ruby

@boulder_ruby - ...це просто заповнювач будь-якого номера.
Ітаї Фербер

126

NSNumberпредмети незмінні; найкраще, що ви можете зробити, це схопити примітивне значення, збільшуючи його, а потім обернути результат у власний NSNumberоб’єкт:

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

28
Сучасні мови: 1, Завдання-С: 0.
devios1

77

Для всіх, хто використовує останню версію Xcode (пишемо це станом на 4.4.1, SDK 5.1), за допомогою об’єктних літералів ви можете очистити код ще трохи ...

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

Як і раніше боліть боротися з боксом і розпаковувати все, щоб робити прості операції, але це стає краще, або принаймні коротше.


6
@softRli Перевірте clang.llvm.org/docs/ObjectiveCLiterals.html, щоб побачити більше ObjC Literals! Дуже зручний imo.
човен

1
І з цього приводу ви можете використовувати x - @ (x.intValue + 1), хоча багатьом людям не подобається використовувати позначення крапок для виклику невластивих методів. Це коротше, але його можна назвати зловживанням позначенням крапки.
Дункан C

@boulder_ruby, це перепризначення. NSNumbers незмінні, тому, щоб "збільшити" значення, ви насправді повинні перепризначити його до нового значення.
shortstuffsushi

30

NSNumbers незмінні, вам потрібно створити новий екземпляр.

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

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

24

Зберіть їх усі разом, і у вас є:

myNSNumber = @(myNSNumber.intValue + 1);

ви не перепризначили тут значення myNSNumber? Я думав, що це не дозволено, оскільки NSNumberоб’єкти незмінні (?)
boulder_ruby

1
Ви створюєте новий об’єкт NSNumber. myNSNumber - це вказівник (NSNumber *) і має нове значення, коли закінчите.
JLundell

3

Мені подобається крапковий вираз, тому що він більш короткий і саме тому IOS підтримує його в першу чергу:

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

точкове позначення не робить те, що ви думаєте, і може бути повільнішим часом (це може бути за замовчуванням "valueForKey:" якщо не існує синтезованого аксесуара для "властивості" (у вашому випадку intValue). intValue ніколи не визначався як @property з NSNumber.
Motti Shneor

2

Якщо ви використовуєте його для зберігання цілісного значення:

myNSNumber = @(myNSNumber.longLongValue + 1);

Для матеріалів з плаваючою крапкою коротка відповідь полягає в наступному, але це погана ідея зробити це, ви втратите точність, і якщо ви будете робити якесь порівняння пізніше, як [myNSNumber isEqual: @ (4.5)], ви можете бути здивовані :

myNSNumber = @(myNSNumber.floatValue + 1);

Якщо вам потрібно зробити математику на числах з плаваючою комою, представленими як об'єкти в Objective-C (тобто, якщо вам потрібно помістити їх у масиви, словники тощо), ви повинні використовувати NSDecimalNumber.


Якщо ви збираєтесь брати участь у голосі, може бути конструктивним і скажіть чому.
lms

З вашої відповіді випливає, що саме NSNumber вводить закруглені неприємності. Це невірно, NSNumber має таку ж поведінку округлення, як і скалярні типи. Також ваша порада використовувати NSDecimalNumbers дуже дратує. Там ви маєте на увазі, що вони необхідні, якщо вам потрібні об'єкти перших громадян у onmbjective-c. Але, звичайно, і кількість об’єктів. NSDecimalNumbers мають більш високу точність, але помилка округлення також може виникнути з ними. І: op запитує про збільшення, ваша відповідь поплавком і подвійною арифметикою. Але вони не мають приросту, оскільки вони не мають природного спадкоємця.
vikingosegundo

@vikingosegundo Це перетворення NSNumber у поплавок, що спричиняє втрату точності, оскільки NSNumber абстрактно зберігає номери там, де float є base2, тож це не вина NSNumber, а конверсія туди і назад. І NSDecimalNumbers буде НЕ причина помилок округлення для base10 арифметичних, і вони будуть призначені для арифметика, прочитати документ. ОП запитала про збільшення NSNumber, і я дав йому правильну і читаючу відповідь на цілісний випадок, а також дав відповідь на випадок з плаваючою комою, але порадив його, а потім надав кращу пропозицію.
lms

Екземпляр може представляти будь-яке число, яке може бути виражене як показник mantissa x 10, де mantissa - це десятковий ціле число довжиною до 38 цифр, а exponent - ціле число між -128 та 127. Не кожне число може бути виражене таким чином. Також ОП попросив легкого збільшення. NSDecimalNumber цього не передбачає. і все ж ваша відповідь означає, що вам потрібні NSDecimalNumbers в об'єктному просторі. це неправильно.
vikingosegundo

Чувак, я намагався бути щиро корисним своєю відповіддю, і подумав, що голосування є в тому, що я щось не так, і думав, що можу дізнатися щось нове. Я зараз бачу, що це не так. Ваші коментарі не мають сенсу, і я пропоную вам ознайомитись із системами числення, тому що базове число 10 є системою. (Повторюючи цитату) не спричинить жодних помилок округлення для базових 10 нумів, я нічого не говорив про точність, просто точність, але 128 десятків теж має велику точність.
lms

0

Використовуйте категорію, щоб полегшити майбутнє використання. Ось основна ідея.

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

Тьфу. Категорія, яка реалізує метод екземпляра, який замінює self?!? Це серйозно неприємно. Чому б не написати метод екземпляра, який має недійсне повернення отриманого NSNumber.
Дункан C

NSNumber визначається як непорушний, отже, цей метод категорії порушує його передбачувану незмінність (навіть якщо замінює себе). Краще розроблена така категорія замість цього додала б новий ініціалізатор до NSNumber у вигляді: + numberByIncrementingAmounf: (int) сума;
Motti Shneor

0

Багато відповідей на відповіді на це питання. Я використав вибрану відповідь у своєму коді, і вона спрацювала. Потім я почав читати решту публікацій і багато спростив код. Це трохи важче читати, якщо ви не знайомі зі змінами нотацій, які були внесені в Xcode 5, але це набагато чистіше. Я, мабуть, міг би зробити це лише одним рядком, але тоді трохи важко зрозуміти, що я роблю.

Я зберігаю NSNumber у словнику і хочу збільшити його. Я отримую його, перетворюю його в int, збільшуючи при перетворенні в NSNumber, після чого повертаю його назад у словник.

Старий кодекс

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

Новий код

NSNumber *correct = [scoringDictionary objectForKey:@"correct"];
scoringDictionary[@"correct"] = @(correct.intValue + 1);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.