NSNumberをインクリメントする方法


108

NSNumberをインクリメントするにはどうすればよいですか?

つまり、myNSNumber ++


2
注意:を使用するときはNSNumber *、必ずプリミティブ型で十分かどうかを確認してください。
WKS 2013年

1
値を増やすためにクエリ、結合、新しいオブジェクトの作成を行う必要があるため、ループ内でこれを実行すると時間がかかる可能性があるため、これを行うための高速/最適化された方法を提供する答えがないことに驚きます。
PetrV 2014年

回答:


123

更新:参考までに、私は個人的にはBoltClockとDarkDustsの1行回答の方が好きです。それらはより簡潔であり、追加の変数を必要としません。


をインクリメントするには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
これが、Core DataのNSNumberプロパティが嫌いな最大の理由です。NSNumberは、数学を操作して実行するのに非常に不便です。
Christian Schlensker、2011年

NSNumberがゼロで初期化されている間は機能せず、ガベージ値が返されます。
Jignesh B

申し訳ありませんが、何の...略ですか?疑似コード参照でしょ?XCodeは対応していません...
boulder_ruby 14

@boulder_ruby ...は、必要な数のプレースホルダーにすぎません。
Itai Ferber 14

126

NSNumberオブジェクトは不変です。あなたができる最善の方法は、プリミティブ値を取得し、それをインクリメントしてから、結果を独自のNSNumberオブジェクトにラップすることです。

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

28
現代の言語:1、オブジェクティブC: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リテラルを参照してください!とても便利なイモ。
チャウン

1
さらに、x-@(x.intValue + 1)を使用することもできますが、多くの人々は、ドット表記を使用して非プロパティメソッドを呼び出すことを好みません。短いですが、ドット表記の乱用と呼ぶことができます。
ダンカンC

@boulder_ruby、それは再割り当てです。NSNumbersは不変なので、値を「インクリメント」するには、実際には新しい値に再割り当てする必要があります。
shortstuffsushi 2014

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オブジェクトは不変(?)
なので

1
新しいNSNumberオブジェクトを作成しています。myNSNumberはポインター(NSNumber *)であり、完了すると新しい値になります。
JLundell 2014

3

ドット式の方が簡潔で、IOSがそもそもサポートしているので、ドット式が好きです。

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

ドット表記はあなたの考えていることをしておらず、時々遅くなる可能性があります(「property」(あなたの場合はintValue)の合成アクセサが存在しない場合、デフォルトで「valueForKey:」になる可能性があります。intValueが@propertyとして定義されたことはありませんののNSNumber。
Motti Shneor

2

整数値を格納するためにそれを使用している場合:

myNSNumber = @(myNSNumber.longLongValue + 1);

浮動小数点のものについての短い答えは次のとおりですが、これを行うことは悪い考えです。精度が失われ、後で[myNSNumber isEqual:@(4.5)]のような種類の比較を行っている場合、驚くかもしれません:

myNSNumber = @(myNSNumber.floatValue + 1);

Objective-Cでオブジェクトとして表される浮動小数点数を計算する必要がある場合(つまり、配列、辞書などに配置する必要がある場合)は、を使用する必要がありますNSDecimalNumber


反対票を投じる場合は、建設的であり、その理由を述べることもできます。
lms 2013年

あなたの答えは、NSNumberが四捨五入の問題を引き起こすことを意味しています。不正解です。NSNumberの丸め動作はスカラー型と同じです。また、NSDecimalNumbersを使用するためのアドバイスは非常にイライラします。そこでは、onmbjective-cで最初の市民オブジェクトが必要な場合にそれらが必要であることを暗示しています。もちろん、オブジェクトのnsnumbersも同様です。NSDecimalNumbersの方が精度が高くなりますが、丸め誤差も発生する可能性があります。そして:opはインクリメントについて尋ね、floatとdoubleの算術による答えを求めます。しかし、それらには自然な後継者がいないため、増分はありません。
vikingosegundo 2013年

@vikingosegundo NSNumberは、floatがbase2である場所に数値を抽象的に格納するため、NSNumberをfloatに変換します。これは、NSNumberの障害ではなく、変換の前後の障害です。そしてNSDecimalNumbersはなりません原因算術base10のエラーを丸め、そしてそれらがされているドキュメントを読んで、算術演算のために設計されました。OPはNSNumberをインクリメントすることについて質問し、私は彼に整数の場合について正しく読みやすい回答を提供し、浮動小数点の場合についても回答を提供しましたが、それに対して助言し、より良い提案をフォローアップしました。
lms 2013年

インスタンスは、仮数x 10の指数として表現できる任意の数値を表すことができます。仮数は最大38桁の10進整数で、指数は-128から127までの整数です。すべての数値がこのように表現できるわけではありません。また、OPは簡単な増分を求めました。NSDecimalNumberはそれを提供していません。それでもあなたの答えは、オブジェクト空間にNSDecimalNumbersが必要であることを意味します。それは間違いです。
vikingosegundo 2013年

私は自分の答えに真に役立つように努めていたのですが、反対票は何か間違ったことによるものであり、何か新しいことを学ぶかもしれないと思ったのです。今はそうではありません。あなたのコメントは意味がありません、そして私はあなたが数システムで読むuoを持っていることをお勧めします。(あなたの引用)は、10を底とする数値に対して丸め誤差を引き起こしません。精度については何も言わず、正確さだけですが、10進数128も十分な精度です。
lms 2013年

0

将来の使用を容易にするためにカテゴリを使用します。これが基本的な考え方です。

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

ああ。自分を置き換えるインスタンスメソッドを実装するカテゴリ?!?それはひどく厄介です。結果のNSNumberのvoid以外の戻り値を持つインスタンスメソッドを作成しないでください。
ダンカンC

NSNumberは不変であると定義されているため、このカテゴリメソッドは、想定される不変性(自己を置き換えた場合でも)に違反しています。より適切に設計されたそのようなカテゴリは、代わりに次の形式で新しい初期化子をNSNumberに追加します。+ numberByIncrementingAmounf:(int)amount;
Motti Shneor

0

この質問への回答にはたくさんの良い情報があります。私はコードで選択した回答を使用し、それが機能しました。その後、残りの投稿を読み始め、コードを大幅に簡略化しました。Xcode 5で導入された表記法の変更に慣れていないと、少し読みづらくなりますが、かなりわかりやすくなっています。たぶん1行にすることもできますが、何をしているのか理解するのが少し難しいです。

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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.