Como converter um NSString em um NSNumber


569

Como se pode converter um NSStringcontendo um número de qualquer tipo de dados primitivos (por exemplo int, float, char, unsigned int, etc.)? O problema é que não sei qual tipo de número a string conterá em tempo de execução.

Eu tenho uma idéia de como fazê-lo, mas não tenho certeza se isso funciona com qualquer tipo, também com valores de ponto flutuante e sem sinal:

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

Obrigado pela ajuda.

Respostas:


1245

Use um NSNumberFormatter:

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

Se a sequência não for um número válido, myNumberserá nil. Se é um número válido, agora você tem toda a NSNumberbondade de descobrir que tipo de número ele realmente é.


16
Para pessoas que parecem não funcionar: verifique se está relacionado ao seu local. O NSNumberFormatter (até onde eu sei) por padrão usa o código do idioma dos EUA, ou seja, espera que o separador decimal seja o "." personagem. Se você usar "," para separar a fração, pode ser necessário informar o formatador para usar seu local atual: [f setLocale: [NSLocale currentLocale]];
pille 28/09

2
@pille por padrão, o código do idioma é o +currentLocale, mas você está correto; é preciso sempre considerar o código do idioma ao lidar com a conversão de itens de e para a forma legível por humanos.
Dave DeLong

Onde você achou que era currentLocale por padrão? Posso confirmar que numberFromString está usando notação de ponto, mesmo em um telefone francês em que a vírgula é usada. Posso confirmar que, por padrão, quando você saída de um número, ele usa o local atual por padrão
allaire

Mas e se a string puder conter int ou float?
GeneCode 9/16/16

179

Você pode usar -[NSString integerValue], -[NSString floatValue]etc. No entanto, a maneira correta (sensível ao código do idioma, etc.) é usar o -[NSNumberFormatter numberFromString:]que fornecerá um NSNumber convertido do código do idioma apropriado e as configurações do NSNumberFormatter(incluindo se ele permitirá flutuação valores pontuais).


27
+ q Dependendo da situação, não sensível ao código do idioma pode realmente ser o caminho correto.
Thilo

2
Eu tive que converter @"2000"para um inte [@"2000" integerValue]funcionou bem e é um pouco mais simples para o meu caso.
Besi

2
Também existem grandes diferenças de desempenho entre esses métodos.
Tom Andersen

2
isso não funciona com o ARC: não converterá o NSInteger em NSNumber. Eu tenho que usar mais[NSNumber numberWithInteger ...]
aluno

O que @Thilo disse. "Correto" e "sensível ao código do idioma" não são sinônimos. A coisa correta a fazer depende na verdade de como o número entrou na string em primeiro lugar. Se você ler a partir da entrada do usuário, é sensível ao local. De qualquer outra fonte (ou seja, você a coloca lá de forma programática, você a está consumindo como parte da resposta de alguma API externa etc.) sensível ao local não é apropriado e pode até dar resultados incorretos.
Aroth 9/03/16

138

Objetivo-C

(Observação: esse método não funciona bem com localidades diferentes, mas é um pouco mais rápido que a NSNumberFormatter)

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

Rápido

Maneira simples, mas suja

// 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)

O caminho da extensão Isso é melhor, realmente, porque vai funcionar bem com códigos de idioma e decimais.

extension String {

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

Agora você pode simplesmente fazer:

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

1
Eu prefiro isso com base em criação de perfil quando estava analisando uma grande quantidade de valores de sequência. O uso dessa sintaxe em vez de um NSNumberFormatter levou a uma redução significativa no tempo gasto analisando a seqüência de caracteres em NSNumber. E sim, o NSNumberFormatter foi armazenado em cache e reutilizado.
androider

3
essa sintaxe literal não existia quando essa pergunta foi feita. Eu diria que esta é a resposta correta hoje em dia.
Chris

1
Eu concordo, mas note que alguns outros países usam o ,e .o outro em torno de forma (por exemplo, 42.000,42alguma coisa. floatValueProvavelmente não leva em conta?
Kevin R

1
Esta é a melhor solução aqui, no entanto, acabei de executar um teste e você perderá a precisão não assinada.
Stoff81

No meu caso de uso, eu precisava obter uma chave de dicionário NSNumber de um NSString, para que @([@"42" intValue])funcionasse perfeitamente. Não estou preocupado com o local.
Chuck Krutsinger

86

Para cadeias começando com números inteiros, por exemplo, @"123", @"456 ft", @"7.89", etc., o uso -[NSString integerValue].

Então, @([@"12.8 lbs" integerValue])é como fazer [NSNumber numberWithInteger:12].


50

Você também pode fazer isso:

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

Diverta-se!


26

Se você souber que recebe números inteiros, poderá usar:

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

11

Aqui está um exemplo de trabalho do NSNumberFormatter lendo o número localizado NSString (xCode 3.2.4, osX 10.6), para salvar outras pessoas das horas que passei brincando. Cuidado: embora ele possa lidar com espaços em branco à direita (funciona "8.765,4"), isso não pode lidar com espaços em branco à esquerda e caracteres de texto dispersos. (Sequências de entrada incorretas: "8" e "8q" e "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

isso não funciona para mim. Estou desenvolvendo para 5.0 com o xcode 4.3.2. alguma idéia por que?
Acecapades


5

Obrigado a todos! Eu sou um feedback combinado e, finalmente, consigo converter da entrada de texto (string) para Inteiro. Além disso, poderia me dizer se a entrada é um número inteiro :)

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

Eu acho que NSDecimalNumber fará isso:

Exemplo:

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

NSDecimalNumber é uma subclasse de NSNumber, portanto, a conversão implícita é permitida.


2

E o padrão do C atoi?

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

Você acha que existem algumas ressalvas?



2

você também pode fazer como este código 8.3.3 ios 10.3 support

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

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


0

Eu sei que é muito tarde, mas o código abaixo está funcionando para mim.

Experimente este código

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

Isso pode ajudá-lo. obrigado


0

Tente isto

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

Nota - usei longLongValue conforme minha exigência. Você também pode usar integerValue, longValue ou qualquer outro formato, dependendo dos seus requisitos.


-1
extension String {

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

let someFloat = "12.34".numberValue
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.