Cómo convertir un NSString en un NSNumber


569

¿Cómo puedo convertir una NSStringque contiene un número de cualquier tipo de datos primitivo (por ejemplo int, float, char, unsigned int, etc.)? El problema es que no sé qué tipo de número contendrá la cadena en tiempo de ejecución.

Tengo una idea de cómo hacerlo, pero no estoy seguro de si esto funciona con algún tipo, también con valores de coma flotante y sin signo:

long long scannedNumber;
NSScanner *scanner = [NSScanner scannerWithString:aString];
[scanner scanLongLong:&scannedNumber]; 
NSNumber *number = [NSNumber numberWithLongLong: scannedNumber];

Gracias por la ayuda.

Respuestas:


1245

Use un NSNumberFormatter:

NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
f.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *myNumber = [f numberFromString:@"42"];

Si la cadena no es un número válido, entonces myNumberlo será nil. Si es un número válido, ahora tiene toda la NSNumberbondad para descubrir qué tipo de número es realmente.


16
Para las personas donde parece que no funciona: compruebe si está relacionado con su entorno local. NSNumberFormatter (hasta donde yo sé) utiliza de forma predeterminada la configuración regional de EE. UU., Es decir, espera que el separador decimal sea el "." personaje. Si usa "," para separar la fracción, es posible que deba indicarle al formateador que use su ubicación actual: [f setLocale: [NSLocale currentLocale]];
pille

2
@pille por defecto, la configuración regional es +currentLocale, pero estás en lo correcto; siempre se debe tener en cuenta el entorno local cuando se trata de convertir cosas de forma legible por humanos.
Dave DeLong el

¿Dónde descubriste que era currentLocale por defecto? Puedo confirmar que numberFromString está usando la notación de puntos incluso en un teléfono francés donde se usa la coma. Puedo confirmar que, de forma predeterminada, cuando
genera

Pero, ¿qué pasa si la cadena puede contener int o float?
GeneCode

179

Puede usar -[NSString integerValue], -[NSString floatValue]etc. Sin embargo, la forma correcta de hacerlo (sensible a la configuración regional, etc.) es usar una -[NSNumberFormatter numberFromString:]que le dará un NSNumber convertido de la configuración regional apropiada y la configuración de NSNumberFormatter(incluyendo si permitirá la flotación valores puntuales).


27
+ q Dependiendo de la situación, no sensible a la configuración regional podría ser la forma correcta.
Thilo

2
Tuve que convertirme @"2000"a inty [@"2000" integerValue]funcionó bien y es un poco más simple para mi caso.
Besi

2
También hay grandes diferencias de rendimiento entre estos métodos.
Tom Andersen

2
esto no funciona con ARC: no convertirá NSInteger a NSNumber. Tengo que usarlo más[NSNumber numberWithInteger ...]
alumno el

Lo que dijo @Thilo. "Correcto" y "sensible a la configuración regional" no son sinónimos. Lo correcto en realidad depende de cómo el número entró en la cadena en primer lugar. Si lo lees desde la entrada del usuario, entonces lo local es lo que quieres. De cualquier otra fuente (es decir, si lo coloca allí mediante programación, lo está consumiendo como parte de la respuesta de alguna API externa, etc.), no es apropiado local-sensible e incluso podría dar resultados incorrectos.
Aroth

138

C objetivo

(Nota: este método no funciona bien con las configuraciones regionales de diferencia, pero es un poco más rápido que a NSNumberFormatter)

NSNumber *num1 = @([@"42" intValue]);
NSNumber *num2 = @([@"42.42" floatValue]);

Rápido

Manera simple pero sucia

// Swift 1.2
if let intValue = "42".toInt() {
    let number1 = NSNumber(integer:intValue)
}

// Swift 2.0
let number2 = Int("42')

// Swift 3.0
NSDecimalNumber(string: "42.42") 

// Using NSNumber
let number3 = NSNumber(float:("42.42" as NSString).floatValue)

La forma de extensión Esto es mejor, realmente, porque jugará muy bien con configuraciones regionales y decimales.

extension String {

    var numberValue:NSNumber? {
        let formatter = NSNumberFormatter()
        formatter.numberStyle = .DecimalStyle
        return formatter.number(from: self)
    }
}

Ahora simplemente puedes hacer:

let someFloat = "42.42".numberValue
let someInt = "42".numberValue

1
Prefiero esto basado en la creación de perfiles cuando estaba analizando una gran cantidad de valores de cadena. El uso de esta sintaxis en lugar de un NSNumberFormatter condujo a una reducción significativa en el tiempo dedicado a analizar la cadena a NSNumber. Y sí, NSNumberFormatter fue almacenado en caché y reutilizado.
androider

3
esta sintaxis literal no existía cuando se hizo esta pregunta. Sin embargo, diría que esta es la respuesta correcta hoy en día.
Chris

1
Estoy de acuerdo, pero tenga en cuenta que algunos otros países usan el ,y .al revés (por ejemplo 42.000,42. ¿Algo que floatValueprobablemente no tiene en cuenta?
Kevin R

1
Esta es la mejor solución aquí, sin embargo, acabo de ejecutar una prueba y perderás la precisión sin firmar, ¡así que CUIDADO!
Stoff81

En mi caso de uso, necesitaba obtener una clave de diccionario NSNumber de un NSString, por lo que @([@"42" intValue])funcionó perfectamente. No me preocupa Locale.
Chuck Krutsinger

86

Para las cadenas que comienzan con números enteros, por ejemplo, @"123", @"456 ft", @"7.89", etc, el uso -[NSString integerValue].

Entonces, @([@"12.8 lbs" integerValue])es como hacer [NSNumber numberWithInteger:12].


50

También puedes hacer esto:

NSNumber *number = @([dictionary[@"id"] intValue]]);

¡Que te diviertas!


26

Si sabe que recibe números enteros, puede usar:

NSString* val = @"12";
[NSNumber numberWithInt:[val intValue]];

11

Aquí hay una muestra funcional de NSNumberFormatter que lee el número localizado NSString (xCode 3.2.4, osX 10.6), para ahorrarle a los demás las horas que acabo de perder. Cuidado: aunque puede manejar espacios en blanco finales ("8,765.4" funciona), esto no puede manejar espacios en blanco iniciales y esto no puede manejar caracteres de texto extraviados. (Cadenas de entrada incorrectas: "8" y "8q" y "8 q".)

NSString *tempStr = @"8,765.4";  
     // localization allows other thousands separators, also.
NSNumberFormatter * myNumFormatter = [[NSNumberFormatter alloc] init];
[myNumFormatter setLocale:[NSLocale currentLocale]]; // happen by default?
[myNumFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
     // next line is very important!
[myNumFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; // crucial

NSNumber *tempNum = [myNumFormatter numberFromString:tempStr];
NSLog(@"string '%@' gives NSNumber '%@' with intValue '%i'", 
    tempStr, tempNum, [tempNum intValue]);
[myNumFormatter release];  // good citizen

Esto no funciona para mí. Estoy desarrollando para 5.0 con xcode 4.3.2. alguna idea de por qué?
acecapades


5

¡Gracias a todos! Me combinan los comentarios y finalmente logro convertir la entrada de texto (cadena) a Entero. Además, podría decirme si la entrada es entera :)

NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * myNumber = [f numberFromString:thresholdInput.text];

int minThreshold = [myNumber intValue]; 

NSLog(@"Setting for minThreshold %i", minThreshold);

if ((int)minThreshold < 1 )
{
    NSLog(@"Not a number");
}
else
{
    NSLog(@"Setting for integer minThreshold %i", minThreshold);
}
[f release];

4

Creo que NSDecimalNumber lo hará:

Ejemplo:

NSNumber *theNumber = [NSDecimalNumber decimalNumberWithString:[stringVariable text]]];

NSDecimalNumber es una subclase de NSNumber, por lo que se permite la conversión implícita.


2

¿Qué pasa con el estándar de C atoi?

int num = atoi([scannedNumber cStringUsingEncoding:NSUTF8StringEncoding]);

¿Crees que hay algunas advertencias?



2

también puede hacer como este código 8.3.3 ios 10.3 soporte

[NSNumber numberWithInt:[@"put your string here" intValue]]

1
NSDecimalNumber *myNumber = [NSDecimalNumber decimalNumberWithString:@"123.45"];
NSLog(@"My Number : %@",myNumber);


0

Sé que esto es muy tarde, pero el siguiente código está funcionando para mí.

Prueba este código

NSNumber *number = @([dictionary[@"keyValue"] intValue]]);

Esto puede ayudarte. Gracias


0

Prueba esto

NSNumber *yourNumber = [NSNumber numberWithLongLong:[yourString longLongValue]];

Nota: he usado longLongValue según mi requisito. También puede usar integerValue, longValue o cualquier otro formato, según sus requisitos.


-1
extension String {

    var numberValue:NSNumber? {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter.number(from: self)
    }
}

let someFloat = "12.34".numberValue
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.