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.

Enyra
fuente

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.

Dave DeLong
fuente
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).

Barry Wark
fuente
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
Kevin R
fuente
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].

ma11hew28
fuente
50

También puedes hacer esto:

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

¡Que te diviertas!

MacMark
fuente
26

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

NSString* val = @"12";
[NSNumber numberWithInt:[val intValue]];
Ad1905
fuente
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
miker
fuente
Esto no funciona para mí. Estoy desarrollando para 5.0 con xcode 4.3.2. alguna idea de por qué?
acecapades
6

Quería convertir una cadena a un doble. Esta respuesta anterior no funcionó para mí. Pero esto hizo: ¿Cómo hacer conversiones de cadenas en Objective-C?

Todo lo que hice fue:

double myDouble = [myString doubleValue];
Antonio
fuente
Esto no convierte el NSInteger en un NSNumber. Lo convierte a un doble.
FabKremer
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];
Laboratorio de aplicaciones de ADN
fuente
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.

JeanNicolas
fuente
2

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

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

¿Crees que hay algunas advertencias?

martín
fuente
2

Puedes usar [string intValue]o [string floatValue]o[string doubleValue] etc.

También puedes usar NSNumberFormatterclass:

usuario1479883
fuente
2

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

[NSNumber numberWithInt:[@"put your string here" intValue]]
Parv Bhasker
fuente
1
NSDecimalNumber *myNumber = [NSDecimalNumber decimalNumberWithString:@"123.45"];
NSLog(@"My Number : %@",myNumber);
Sandip Patel - SM
fuente
0

Trabajó en Swift 3

NSDecimalNumber(string: "Your string") 
usuario431791
fuente
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

Ashu
fuente
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.

Rizwan Ahmed
fuente
-1
extension String {

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

let someFloat = "12.34".numberValue
Ankit Garg
fuente