Jak przekonwertować NSString na numer NSNumber

569

Jak mogę przekonwertować NSStringzawierający szereg jakiegokolwiek prymitywnego typu danych (np int, float, char, unsigned int, itd.)? Problem polega na tym, że nie wiem, jaki typ numeru będzie zawierał łańcuch w czasie wykonywania.

Mam pomysł, jak to zrobić, ale nie jestem pewien, czy to działa z dowolnym typem, także z wartościami niepodpisanymi i zmiennoprzecinkowymi:

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

Dzięki za pomoc.

Enyra
źródło

Odpowiedzi:

1245

Użyj NSNumberFormatter:

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

Jeśli ciąg nie jest poprawną liczbą, to myNumberbędzie nil. Jeśli jest to poprawna liczba, masz teraz całą NSNumberdobroć, aby dowiedzieć się, jaki to jest rzeczywiście numer.

Dave DeLong
źródło
16
Dla osób, w których wydaje się, że to nie działa: Sprawdź, czy jest to związane z twoimi ustawieniami regionalnymi. NSNumberFormatter (o ile mi wiadomo) domyślnie używa ustawień regionalnych w USA, tj. Oczekuje, że separatorem dziesiętnym będzie „.” postać. Jeśli użyjesz „,”, aby oddzielić ułamek, może być konieczne poinformowanie formatyzatora, aby używał twoich bieżących ustawień regionalnych: [f setLocale: [NSLocale currentLocale]];
pille
2
@ pille domyślnie jest to ustawienie regionalne +currentLocale, ale masz rację; zawsze trzeba brać pod uwagę lokalizację, gdy mamy do czynienia z konwertowaniem rzeczy do postaci czytelnej dla człowieka.
Dave DeLong
Gdzie znalazłeś, że domyślnie jest to currentLocale? Mogę potwierdzić, że numberFromString używa notacji kropkowej nawet na francuskim telefonie, w którym używany jest przecinek. Mogę potwierdzić, że domyślnie, gdy
wypisujesz
Ale co jeśli ciąg może zawierać int lub float?
GeneCode
179

Można użyć -[NSString integerValue], -[NSString floatValue]itp Jednak prawidłowe (locale wrażliwych, etc.) sposobem, aby to zrobić jest użycie -[NSNumberFormatter numberFromString:]który daje NSNumber przeliczona z odpowiedniej lokalizacji i biorąc pod uwagę ustawienia NSNumberFormatter(w tym, czy pozwoli to pływający wartości punktowe).

Barry Wark
źródło
27
+ q W zależności od sytuacji, niewrażliwy na ustawienia regionalne może być właściwie właściwy sposób.
Thilo,
2
Musiałem przekonwertować @"2000"na inti [@"2000" integerValue]działało ładnie i jest trochę prostsze w moim przypadku.
Besi
2
Istnieją również ogromne różnice w wydajności między tymi metodami.
Tom Andersen
2
to nie działa z ARC: nie przekonwertuje NSInteger na NSNumber. Muszę dalej korzystać[NSNumber numberWithInteger ...]
uczeń
Co powiedział @Thilo. „Prawidłowe” i „wrażliwe na ustawienia regionalne” nie są synonimami. Właściwa czynność zależy od tego, w jaki sposób liczba dostała się do ciągu. Jeśli czytasz to na podstawie danych wprowadzonych przez użytkownika, wrażliwość lokalna jest tym, czego chcesz. Z jakiegokolwiek innego źródła (tj. Umieszczasz go tam programowo, zużywasz go jako część odpowiedzi z zewnętrznego interfejsu API itp.) Wrażliwość lokalna nie jest odpowiednia, a nawet może dawać nieprawidłowe wyniki.
aroth
138

Cel C

(Uwaga: ta metoda nie działa dobrze z różnicami lokalizacji, ale jest nieco szybsza niż a NSNumberFormatter)

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

Szybki

Prosty, ale brudny sposób

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

Sposób rozszerzenia Jest to naprawdę lepsze, ponieważ będzie dobrze grało z ustawieniami narodowymi i dziesiętnymi.

extension String {

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

Teraz możesz po prostu zrobić:

let someFloat = "42.42".numberValue
let someInt = "42".numberValue
Kevin R.
źródło
1
Wolę to na podstawie profilowania, gdy analizowałem dużą liczbę wartości ciągów. Zastosowanie tej składni zamiast NSNumberFormatter doprowadziło do znacznego skrócenia czasu poświęcanego na analizowanie łańcucha do NSNumber. I tak, NSNumberFormatter został zbuforowany i ponownie użyty.
androider
3
ta dosłowna składnia nie istniała, gdy zadano to pytanie. Powiedziałbym jednak, że obecnie jest to poprawna odpowiedź.
Chris
1
Zgadzam się, ale zauważam, że niektóre inne kraje używają ,i .odwrotnie (np 42.000,42. Coś floatValueprawdopodobnie nie odpowiada?
Kevin R
1
To najładniejsze rozwiązanie tutaj, jednak właśnie przeprowadziłem test i stracisz niepodpisaną precyzję, więc OBEJRZYJ !!!
Stoff81
W moim przypadku musiałem uzyskać klucz słownika NSNumber z NSString, więc @([@"42" intValue])działało idealnie. Nie martwię się o ustawienia regionalne.
Chuck Krutsinger
86

Ciągów rozpoczynających się z liczb całkowitych, na przykład @"123", @"456 ft", @"7.89"itd wykorzystanie -[NSString integerValue].

To @([@"12.8 lbs" integerValue])jest jak robienie [NSNumber numberWithInteger:12].

ma11hew28
źródło
50

Możesz także to zrobić:

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

Baw się dobrze!

MacMark
źródło
26

Jeśli wiesz, że otrzymujesz liczby całkowite, możesz użyć:

NSString* val = @"12";
[NSNumber numberWithInt:[val intValue]];
Ad1905
źródło
11

Oto działająca próbka odczytu NSNumberFormatter zlokalizowanej liczby NSString (xCode 3.2.4, osX 10.6), aby zaoszczędzić innym godzinom, które właśnie spędziłem na zabawie. Uwaga: chociaż może obsługiwać końcowe spacje (działa „8765.4”), nie obsługuje wiodących białych znaków i nie może obsłużyć zbłąkanych znaków tekstowych. (Niepoprawne ciągi wejściowe: „8” i „8q” i „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
źródło
to nie działa dla mnie. Zajmuję się wersją 5.0 z xcode 4.3.2. jakieś pomysły dlaczego?
acecapades
6

Chciałem przekonwertować ciąg znaków na podwójny. Ta powyższa odpowiedź nie do końca działała dla mnie. Ale tak się stało: jak wykonać konwersję ciągu w Objective-C?

Wszystko, co właściwie zrobiłem, to:

double myDouble = [myString doubleValue];
Anthony
źródło
Nie powoduje to konwersji NSInteger na numer NSNumber. Konwertuje to na podwójne.
FabKremer,
5

Dziękuje wszystkim! Łączą się opinie i wreszcie mogę przekonwertować z wprowadzania tekstu (ciąg) na liczbę całkowitą. Dodatkowo może mi powiedzieć, czy wejście jest liczbą całkowitą :)

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
źródło
4

Myślę, że NSDecimalNumber to zrobi:

Przykład:

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

NSDecimalNumber jest podklasą NSNumber, więc dozwolone jest niejawne rzutowanie.

JeanNicolas
źródło
2

Co ze standardem C atoi?

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

Czy uważasz, że są jakieś zastrzeżenia?

jaskółka oknówka
źródło
2

Możesz po prostu użyć [string intValue]lub [string floatValue]lub [string doubleValue]etc

Możesz także użyć NSNumberFormatterklasy:

użytkownik1479883
źródło
2

możesz również zrobić tak, jak ten kod 8.3.3 ios 10.3 wsparcie

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

Pracował w Swift 3

NSDecimalNumber(string: "Your string") 
użytkownik431791
źródło
0

Wiem, że jest bardzo późno, ale poniższy kod działa dla mnie.

Wypróbuj ten kod

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

To może ci pomóc. Dzięki

Ashu
źródło
0

Spróbuj tego

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

Uwaga - użyłem longLongValue zgodnie z moimi wymaganiami. Możesz również użyć liczby całkowitej, długiej wartości lub dowolnego innego formatu, w zależności od wymagań.

Rizwan Ahmed
źródło
-1
extension String {

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

let someFloat = "12.34".numberValue
Anargit garg
źródło