Как преобразовать NSString в NSNumber

Как я могу преобразовать NSString, содержащий число любого примитивного типа данных (например, int, float, char, unsigned int и т. Д.)? Проблема в том, что я не знаю, какой тип числа будет содержать строка во время выполнения.

У меня есть идея, как это сделать, но я не уверен, работает ли это с любым типом, а также значениями без знака и с плавающей запятой:

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

Спасибо за помощь.


person Enyra    schedule 19.09.2009    source источник


Ответы (16)


Используйте NSNumberFormatter:

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

Если строка не является допустимым числом, тогда myNumber будет nil. Если это действительное число, то теперь у вас есть все NSNumber добро, чтобы выяснить, что это за число на самом деле.

person Dave DeLong    schedule 19.09.2009
comment
Для людей, у которых это не работает: проверьте, не связано ли это с вашим языком. NSNumberFormatter (насколько мне известно) по умолчанию использует локаль США, т.е. ожидает, что десятичным разделителем будет. персонаж. Если вы используете, для разделения дроби, вам может потребоваться указать программе форматирования использовать ваш текущий языковой стандарт: [f setLocale: [NSLocale currentLocale]]; - person pille; 28.09.2012
comment
@pille по умолчанию используется +currentLocale, но вы правы; при преобразовании материалов в удобочитаемую форму и обратно необходимо учитывать региональный стандарт. - person Dave DeLong; 22.11.2012
comment
Где вы обнаружили, что по умолчанию это currentLocale? Я могу подтвердить, что numberFromString использует точечную нотацию даже на французском телефоне, где используется запятая. Я могу подтвердить, что по умолчанию, когда вы выводите число, по умолчанию используется текущий языковой стандарт. - person allaire; 24.07.2015
comment
Но что, если строка может содержать либо int, либо float? - person GeneCode; 09.12.2016

Вы можете использовать -[NSString integerValue], -[NSString floatValue] и т. Д. Однако правильный (с учетом локали и т. Д.) Способ сделать это - использовать -[NSNumberFormatter numberFromString:], который даст вам NSNumber, преобразованный из соответствующей локали и с учетом настроек NSNumberFormatter (включая то, это позволит использовать значения с плавающей запятой).

person Barry Wark    schedule 19.09.2009
comment
+ q В зависимости от ситуации, использование нечувствительности к локали может быть правильным способом. - person Thilo; 12.09.2011
comment
Мне пришлось преобразовать @"2000" в int, и [@"2000" integerValue] работал хорошо и немного проще для моего случая. - person Besi; 02.02.2012
comment
Между этими методами также есть огромная разница в производительности. - person Tom Andersen; 21.06.2013
comment
это не работает с ARC: он не преобразует NSInteger в NSNumber. Мне нужно в дальнейшем использовать [NSNumber numberWithInteger ...] - person learner; 03.08.2014
comment
Что сказал @Thilo. Правильный и зависящий от локали не синонимы. На самом деле, что делать правильно, зависит от того, как число вообще попало в строку. Если вы читаете его из пользовательского ввода, то локально-чувствительный - это то, что вам нужно. Из любого другого источника (т.е. вы помещаете его программно, вы потребляете его как часть ответа от какого-то внешнего API и т. Д.), Чувствительность к локальным условиям не подходит и может даже давать неверные результаты. - person aroth; 09.03.2016

Цель-C

(Примечание: этот метод не очень хорошо работает с разными языковыми стандартами, но немного быстрее, чем NSNumberFormatter)

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

Быстрый

Простой, но грязный способ

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

Способ расширения. На самом деле это лучше, потому что он отлично работает с языковыми стандартами и десятичными знаками.

extension String {

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

Теперь вы можете просто сделать:

let someFloat = "42.42".numberValue
let someInt = "42".numberValue
person Kevin R    schedule 09.12.2013
comment
Я предпочитаю, чтобы это было основано на профилировании, когда я анализировал большое количество строковых значений. Использование этого синтаксиса вместо NSNumberFormatter привело к значительному сокращению времени, затрачиваемого на синтаксический анализ строки до NSNumber. И да, NSNumberFormatter был кэширован и повторно использован. - person androider; 05.03.2014
comment
этот буквальный синтаксис не существовал, когда был задан этот вопрос. Я бы сказал, что сейчас это правильный ответ. - person Chris; 26.09.2014
comment
Я согласен, но учтите, что в некоторых других странах используются , и . наоборот (например, 42.000,42. Что-то floatValue, вероятно, не учитывает? - person Kevin R; 27.10.2014
comment
Это лучшее решение здесь, однако я только что провел тест, и вы потеряете беззнаковую точность, так что ВНИМАТЕЛЬНО !!! - person Stoff81; 28.04.2015
comment
В моем случае мне нужно было получить ключ словаря NSNumber из NSString, поэтому @([@"42" intValue]) работал отлично. Не переживаю за Локаль. - person Chuck Krutsinger; 18.08.2017

Для строк, начинающихся с целых чисел, например @"123", @"456 ft", @"7.89" и т. Д., Используйте _ 4_.

Итак, @([@"12.8 lbs" integerValue]) все равно что делать [NSNumber numberWithInteger:12].

person ma11hew28    schedule 29.09.2010

Вы также можете сделать это:

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

Повеселись!

person MacMark    schedule 05.06.2013

Если вы знаете, что получаете целые числа, вы можете использовать:

NSString* val = @"12";
[NSNumber numberWithInt:[val intValue]];
person Ad1905    schedule 10.04.2012

Вот рабочий образец NSNumberFormatter, считывающий локализованный номер NSString (xCode 3.2.4, osX 10.6), чтобы сэкономить другим время, которое я только что потратил на возню. Осторожно: хотя он может обрабатывать завершающие пробелы (работает «8,765.4»), он не может обрабатывать начальные пробелы и не может обрабатывать случайные текстовые символы. (Неверные входные строки: «8», «8q» и «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
person miker    schedule 25.10.2010
comment
это не работает для меня. Я разрабатываю для 5.0 с xcode 4.3.2. какие идеи почему? - person acecapades; 07.09.2012


Спасибо всем! Я объединил отзывы и, наконец, смог преобразовать текстовый ввод (строку) в целое число. Кроме того, он мог сказать мне, является ли ввод целым :)

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];
person DNA App Lab    schedule 05.03.2011

Я думаю, что NSDecimalNumber сделает это:

Пример:

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

NSDecimalNumber является подклассом NSNumber, поэтому разрешено неявное приведение типов.

person JeanNicolas    schedule 20.07.2013

А как насчет стандарта C atoi?

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

Как вы думаете, есть какие-то оговорки?

person martin    schedule 27.07.2012
comment
ты прочитал вопрос? вы должны предоставить экземпляр NSNumber (объект Objective-C), а не примитив int. - person Motti Shneor; 31.12.2020

Вы можете просто использовать [string intValue], [string floatValue] или [string doubleValue] и т. Д.

Вы также можете использовать _4 _ класс:

person user1479883    schedule 29.01.2014

вы также можете сделать, как этот код, 8.3.3 поддержка ios 10.3

[NSNumber numberWithInt:[@"put your string here" intValue]]
person Parv Bhasker    schedule 07.07.2017

Попробуй это

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

Примечание. Я использовал longLongValue в соответствии с моими требованиями. Вы также можете использовать integerValue, longValue или любой другой формат в зависимости от ваших требований.

person Rizwan Ahmed    schedule 02.11.2017

Работал в Swift 3

NSDecimalNumber(string: "Your string") 
person user431791    schedule 23.09.2016

Я знаю, что это очень поздно, но код ниже работает для меня.

Попробуйте этот код

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

Это может вам помочь. Спасибо

person Ashu    schedule 27.05.2017