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.

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.


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


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

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].


50

Możesz także to zrobić:

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

Baw się dobrze!


26

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

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

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

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];

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];

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.


2

Co ze standardem C atoi?

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

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



2

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

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

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


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


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ń.


-1
extension String {

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

let someFloat = "12.34".numberValue
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.