如何增加一个NSNumber


108

如何增加NSNumber?

即myNSNumber ++


2
请记住:使用时NSNumber *,请始终检查基本类型是否足够。
WKS

1
我很惊讶没有答案提供快速/优化的方法,因为仅仅为了增加价值,您需要查询,合并和创建新对象,因此在循环中执行此操作会很耗时。
PetrV 2014年

Answers:


123

更新:仅供参考,我个人更喜欢BoltClock和DarkDusts的单行答案。它们更加简洁,不需要其他变量。


为了增加an NSNumber,您将必须获取它的值,然后增加它的值并将其存储在new中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 2014年

@boulder_ruby这...只是您想要的任何数字的占位符。
Itai Ferber 2014年

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文字!非常方便的imo。
chown 2012年

1
为此,您可以使用x-@(x.intValue + 1),尽管许多人不喜欢使用点表示法来调用非属性方法。它较短,但是可以称为滥用点表示法。
Duncan C

@boulder_ruby,这是重新分配。NSNumber是不可变的,因此要“增加”值,实际上您必须将其重新分配为新值。
shortstuffsushi

30

NSNumber是不可变的,您必须创建一个新实例。

// 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 2014年

1
您正在创建一个新的NSNumber对象。myNSNumber是一个指针(NSNumber *),完成后具有新值。
JLundell

3

我喜欢点表达式,因为它更简洁,这就是IOS首先支持它的原因:

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

点表示法不能满足您的要求,有时可能会变慢(如果“属性”(在您的情况下为intValue)不存在综合访问器,则默认为“ valueForKey:”。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中的第一个公民对象,那么这些是必需的。但是,当然nsnumbers也指向对象。NSDecimalNumbers的精度更高,但是舍入错误也可能发生。并且:op询问有关递增,浮点和双精度算术的答案。但是这些没有增量,因为它们没有天生的后继者。
vikingosegundo

@vikingosegundo它将NSNumber转换为float会导致精度下降,因为NSNumber抽象地将数字存储在float为base2的位置,所以这不是NSNumber的错误,而是来回转换的错误。NSDecimalNumbers 不会对base10算术产生舍入错误,它们为算术设计的,请阅读文档。OP询问增加一个NSNumber的问题,我给了他一个正确且可读的整数问题答案,还给出了浮点问题的答案,但建议不要这样做,然后提出更好的建议。
lms

一个实例可以表示任何可以表示为尾数x 10指数的数字,其中尾数是最长38位的十进制整数,指数是-128到127之间的整数。并非每个数字都可以这样表示。OP还要求轻松增加。NSDecimalNumber不提供该功能。而且您的答案仍然暗示您需要在对象空间中使用NSDecimalNumbers。那是错的。
vikingosegundo

杜德(Dude),我试图对我的回答提供真正的帮助,并认为不赞成投票是因为我做错了什么,我认为我可能会学到一些新知识。我现在可以看到情况并非如此。您的评论没有任何意义,我建议您阅读数字系统,因为基数为10。(关于您的报价)不会对以10为基数的数引起任何舍入错误,我没有提到精度,只是精度,但是128位十进制也具有足够的精度。
lms 2013年

0

使用类别以简化将来的使用。这是一个基本的想法。

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

啊。一个实现替换self?!?的实例方法的类别。真讨厌 为什么不编写一个实例方法,该方法的结果是非空返回的NSNumber。
Duncan C

NSNumber被定义为不可变的,因此此类别方法违反了其假定的不可变性(即使替换了self)。设计更好的此类应改为向NSNumber添加新的初始化程序,形式为:+ numberByIncrementingAmounf:(int)amount;
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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.