Comment convertir une NSString en un NSNumber

569

Comment puis - je convertir un NSStringcontenant un certain nombre de tout type de données primitive (par exemple int, float, char, unsigned int, etc.)? Le problème est que je ne sais pas quel type de numéro la chaîne contiendra lors de l'exécution.

J'ai une idée de comment le faire, mais je ne sais pas si cela fonctionne avec n'importe quel type, également des valeurs non signées et à virgule flottante:

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

Merci pour l'aide.

Enyra
la source

Réponses:

1245

Utilisez un NSNumberFormatter:

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

Si la chaîne n'est pas un nombre valide, elle le myNumbersera nil. S'il s'agit d'un nombre valide, vous avez maintenant toute la NSNumberbonté de déterminer de quel type de numéro il s'agit.

Dave DeLong
la source
16
Pour les personnes où cela ne semble pas fonctionner: vérifiez si cela est lié à votre environnement local. Le NSNumberFormatter (pour autant que je sache) utilise par défaut les paramètres régionaux américains, c'est-à-dire s'attend à ce que le séparateur décimal soit le "." personnage. Si vous utilisez "," pour séparer la fraction, vous devrez peut-être dire au formateur d'utiliser vos paramètres régionaux actuels: [f setLocale: [NSLocale currentLocale]];
pille
2
@pille par défaut, la locale est la +currentLocale, mais vous avez raison; il faut toujours tenir compte des paramètres régionaux lors de la conversion de trucs vers et depuis une forme lisible par l'homme.
Dave DeLong
Où avez-vous constaté qu'il s'agissait de currentLocale par défaut? Je peux confirmer que numberFromString utilise la notation par points même sur un téléphone français où la virgule est utilisée. Je peux confirmer que par défaut, lorsque vous sortez un nombre, il utilise les paramètres régionaux actuels par défaut
allaire
Mais que faire si la chaîne peut contenir int ou float?
GeneCode
179

Vous pouvez utiliser -[NSString integerValue], -[NSString floatValue]etc. Cependant, la manière correcte (paramètres régionaux, etc.) pour ce faire est d'utiliser ce -[NSNumberFormatter numberFromString:]qui vous donnera un NSNumber converti à partir des environnements locaux appropriés et compte tenu des paramètres du NSNumberFormatter(y compris si elle permettra flottante valeurs en points).

Barry Wark
la source
27
+ q En fonction de la situation, la non-sensibilité locale peut être en fait la bonne façon.
Thilo
2
J'ai dû me convertir @"2000"en un intet j'ai [@"2000" integerValue]bien travaillé et c'est un peu plus simple pour mon cas.
Besi
2
Il existe également d'énormes différences de performances entre ces méthodes.
Tom Andersen
2
cela ne fonctionne pas avec ARC: il ne convertira pas NSInteger en NSNumber. Je dois continuer à utiliser[NSNumber numberWithInteger ...]
apprenant
Ce que @Thilo a dit. "Correct" et "locale-sensitive" ne sont pas synonymes. La bonne chose à faire dépend en fait de la façon dont le nombre est entré dans la chaîne en premier lieu. Si vous le lisez à partir de l'entrée utilisateur, alors vous êtes sensible au local. À partir de toute autre source (c'est-à-dire que vous l'avez mise par programme, vous la consommez dans le cadre de la réponse d'une API externe, etc.), la sensibilité locale n'est pas appropriée et pourrait même donner des résultats incorrects.
aroth
138

Objectif c

(Remarque: cette méthode ne fonctionne pas bien avec les différences de paramètres régionaux, mais est légèrement plus rapide que a NSNumberFormatter)

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

Rapide

Manière simple mais sale

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

L'extension-way C'est mieux, vraiment, car il jouera bien avec les locales et les décimales.

extension String {

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

Maintenant, vous pouvez simplement faire:

let someFloat = "42.42".numberValue
let someInt = "42".numberValue
Kevin R
la source
1
Je préfère cela en fonction du profilage lorsque j'analysais une grande quantité de valeurs de chaîne. L'utilisation de cette syntaxe plutôt qu'un NSNumberFormatter a conduit à une réduction significative du temps passé à analyser la chaîne en NSNumber. Et oui, NSNumberFormatter a été mis en cache et réutilisé.
androider
3
cette syntaxe littérale n'existait pas lorsque cette question a été posée. Je dirais que c'est la bonne réponse de nos jours cependant.
Chris
1
Je suis d'accord, mais notez que certains autres pays utilisent le ,et .l'inverse (par exemple 42.000,42. Quelque chose floatValuene tient probablement pas compte?
Kevin R
1
C'est la meilleure solution ici, mais je viens de faire un test et vous perdrez une précision non signée alors ATTENTION !!!
Stoff81
Dans mon cas d'utilisation, j'avais besoin d'obtenir une clé de dictionnaire NSNumber à partir d'une NSString, donc cela @([@"42" intValue])fonctionnait parfaitement. Pas inquiet pour Locale.
Chuck Krutsinger
86

Pour les chaînes commençant par des nombres entiers, par exemple @"123", @"456 ft", @"7.89", etc., l' utilisation -[NSString integerValue].

C'est @([@"12.8 lbs" integerValue])comme faire [NSNumber numberWithInteger:12].

ma11hew28
la source
50

Vous pouvez également le faire:

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

S'amuser!

MacMark
la source
26

Si vous savez que vous recevez des nombres entiers, vous pouvez utiliser:

NSString* val = @"12";
[NSNumber numberWithInt:[val intValue]];
Ad1905
la source
11

Voici un exemple de travail de NSNumberFormatter lisant le numéro localisé NSString (xCode 3.2.4, osX 10.6), pour économiser aux autres les heures que je viens de passer à jouer. Attention: bien qu'il puisse gérer les blancs de fin ("8 765,4" fonctionne), cela ne peut pas gérer les espaces blancs en tête et cela ne peut pas gérer les caractères de texte errant. (Chaînes d'entrée incorrectes: "8" et "8q" et "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
la source
ça ne marche pas pour moi. Je développe pour 5.0 avec xcode 4.3.2. des idées pourquoi?
acecapades
6

Je voulais convertir une chaîne en double. Cette réponse ci-dessus n'a pas vraiment fonctionné pour moi. Mais cela a fait: Comment faire des conversions de chaînes dans Objective-C?

Tout ce que j'ai fait, c'est:

double myDouble = [myString doubleValue];
Anthony
la source
Cela ne convertit pas NSInteger en NSNumber. Il le convertit en double.
FabKremer
5

Merci a tous! Je suis une rétroaction combinée et parviens enfin à convertir de la saisie de texte (chaîne) en entier. De plus, il pourrait me dire si l'entrée est un entier :)

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];
DNA App Lab
la source
4

Je pense que NSDecimalNumber le fera:

Exemple:

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

NSDecimalNumber est une sous-classe de NSNumber, la conversion implicite est donc autorisée.

JeanNicolas
la source
2

Qu'en est-il de la norme C atoi?

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

Pensez-vous qu'il y ait des mises en garde?

Martin
la source
2

Vous pouvez simplement utiliser [string intValue]ou [string floatValue]ou [string doubleValue]etc.

Vous pouvez également utiliser la NSNumberFormatterclasse:

user1479883
la source
2

vous pouvez également faire comme ce code support 8.3.3 ios 10.3

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

A travaillé dans Swift 3

NSDecimalNumber(string: "Your string") 
user431791
la source
0

Je sais que c'est très tard mais le code ci-dessous fonctionne pour moi.

Essayez ce code

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

Cela peut vous aider. Merci

Ashu
la source
0

Essaye ça

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

Remarque - J'ai utilisé longLongValue selon mes besoins. Vous pouvez également utiliser integerValue, longValue ou tout autre format en fonction de vos besoins.

Rizwan Ahmed
la source
-1
extension String {

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

let someFloat = "12.34".numberValue
Garçon Ankit
la source