2011-01-25 25 views
100

¿Cómo incremento un NSNumber?Cómo incrementar un NSNumber

es decir myNSNumber ++

+2

Recuerde: cuando se utiliza '' NSNumber *, compruebe siempre para ver si son suficientes los tipos primitivos. –

+0

Me sorprende que no haya una respuesta que proporcione una forma rápida/optimizada de hacerlo, porque solo para aumentar el valor necesita consultar, combinar y crear un nuevo objeto, por lo que hacer esto en bucle puede llevar mucho tiempo. – PetrV

Respuesta

119

Actualización: FYI, personalmente me gusta de BoltClock y una línea de DarkDusts contesta mejor. Son más concisos y no requieren variables adicionales.


Con el fin de incrementar la NSNumber, vas a tener que obtener su valor, incremento que, y almacenarlo en una nueva NSNumber.

Por ejemplo, para un NSNumber sosteniendo un entero:

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

o para una NSNumber la celebración de un número de coma flotante:

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

Esta es la razón principal por la que odio las propiedades NSNumber en Core Data. NSNumber es tan inconveniente para trabajar y realizar operaciones matemáticas. –

+0

de nuevo NSNumber no funcionó durante la inicialización con cero dar valor de basura. –

+0

perdón, ¿qué significa el '...'? Eso es una referencia de pseudocódigo, ¿verdad? XCode does not '...' –

122

NSNumber objetos son inmutables; lo mejor que puede hacer es agarrar el valor simple, incrementarlo después envuelva el resultado en su propio NSNumber objeto:

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

Batirme por un segundo ...;) –

+1

Me gusta este one-liner; gracias. –

+24

Idiomas modernos: 1, Objective-C: 0. – devios1

30

NSNumbers son inmutables, usted tiene que crear una nueva instancia .

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

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

Para cualquier persona que está utilizando la última versión de Xcode (escribiendo esto a partir de 4.4.1, 5.1 SDK), con el uso de objetos literales, se puede limpiar el código hasta incluso un poco más .. .

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

Aún así una especie de dolor a tratar con el boxeo y unboxing todo a hacer operaciones simples, pero cada vez es mejor, o al menos más corto.

+0

¡Gracias por contarlo! No había visto esto todavía, y esto es bastante claro – rchampourlier

+6

@softRli ¡Consulte http://clang.llvm.org/docs/ObjectiveCLiterals.html para ver más ObjC Literals! Muy útil imo. – chown

+1

Y para el caso, podría usar x - @ (x.intValue + 1), aunque a muchas personas no les gusta usar la notación de puntos para invocar métodos que no sean de propiedad. Es más corto, pero podría llamarse abuso de la notación de puntos. –

3

me gusta la expresión de puntos porque es más concisa y es por eso IOS lo admite, en primer lugar:

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

poner a todos juntos, y usted tiene:

myNSNumber = @(myNSNumber.intValue + 1); 
+0

¿no estás reasignando el valor de myNSNumber aquí? Pensé que no estaba permitido porque los objetos 'NSNumber' son inmutables (?) –

+1

Está creando un nuevo objeto NSNumber. myNSNumber es un puntero (NSNumber *) y tiene un nuevo valor cuando haya terminado. – JLundell

2

Si usted lo está utilizando para almacenar un valor entero:

myNSNumber = @(myNSNumber.longLongValue + 1); 

F o cosas de coma flotante, la respuesta corta es la siguiente, pero es una mala idea hacer esto, perderás precisión y si estás haciendo algún tipo de comparación más tarde como [myNSNumber isEqual: @ (4.5)] te sorprenderá :

myNSNumber = @(myNSNumber.floatValue + 1); 

Si lo que necesita hacer matemáticas en números de punto representadas como objetos en Objective-C flotante (es decir, si necesita colocarlos en matrices, diccionarios, etc.) debe usar NSDecimalNumber.

+0

Si va a downvote, podría ser constructivo y decir por qué. – lms

+0

Su respuesta implica que es NSNumber que introduce problemas de redondeo. Eso no es correcto, NSNumber tiene el mismo comportamiento de redondeo que los tipos escalares. También su consejo de usar NSDecimalNumbers es bastante irritante. Ahí implica que esos son necesarios si necesita primeros objetos ciudadanos en onjective-c. Pero, por supuesto, también hay números en los objetos. NSDecimalNumbers tiene una mayor precisión, pero el error de redondeo también puede ocurrir con ellos. Y: op pregunta sobre el incremento, tu respuesta con float y aritmética doble. Pero esos no tienen incremento, ya que no tienen un sucesora natural. – vikingosegundo

+0

@vikingosegundo Se está convirtiendo un NSNumber en un flotante que causa la pérdida de precisión porque NSNumber almacena los números de forma abstracta donde float son base2, por lo que no es culpa del NSNumber, sino de la conversión de ida y vuelta. Y NSDecimalNumbers * * no causarán errores de redondeo para la base 10 aritmética, y * están * diseñados para aritmética, lea el documento. El OP preguntó acerca de incrementar un NSNumber, y le di una respuesta correcta y legible para el caso integral, y también le di una respuesta para el caso de punto flotante, pero desaconsejé el tema y luego hice un seguimiento con una mejor sugerencia. – lms

0

Use una categoría para facilitar el uso futuro. Aquí hay una idea básica.

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

Ugh. Una categoría que implementa un método de instancia que reemplaza a self?!? Eso es muy desagradable. ¿Por qué no escribir un método de instancia que tiene un retorno no nulo del NSNumber resultante? –

0

Mucha información buena en las respuestas a esta pregunta. Usé la respuesta seleccionada en mi código y funcionó.Luego comencé a leer el resto de las publicaciones y simplifiqué mucho el código. Es un poco más difícil de leer si no está familiarizado con los cambios en la notación que se introdujeron en Xcode 5, pero es mucho más limpio. Probablemente podría hacer una sola línea, pero luego es un poco difícil de entender lo que estoy haciendo.

Estoy almacenando un NSNumber en un diccionario y quiero incrementarlo. Lo entiendo, lo convierto en un int, lo increméntelo mientras lo convierte a un NSNumber, luego lo vuelvo a poner en el diccionario.

Código antiguo

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

nuevo código

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