Як перетворити NSString в NSNumber


569

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

У мене є ідея, як це зробити, але я не впевнений, чи працює це з будь-яким типом, також неподписаними та значеннями з плаваючою точкою:

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

Дякую за допомогу.

Відповіді:


1245

Використовуйте NSNumberFormatter:

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

Якщо рядок не є дійсним числом, то myNumberбуде nil. Якщо це дійсне число, то тепер у вас є все добре, NSNumberщоб зрозуміти, яке це число насправді.


16
Для людей, де це, здається, не працює: Перевірте, чи це пов’язано з вашим місцем. NSNumberFormatter (наскільки я знаю) за замовчуванням використовує локальний код США, тобто очікує, що десятковий роздільник буде "". характер. Якщо ви використовуєте "," для розділення дробу, можливо, вам потрібно буде сказати форматору використовувати поточний локал: [f setLocale: [NSLocale currentLocale]];
стовп

2
@pille за замовчуванням локаль - це +currentLocale, але ви правильні; завжди слід враховувати локаль при роботі з перетворенням матеріалів у форму, читану людиною і з них.
Дейв ДеЛонг

Де ви виявили, що вона за замовчуванням була поточною локальною? Я можу підтвердити, що numberFromString використовує позначення крапок навіть на французькому телефоні, де використовується кома. Я можу підтвердити, що за замовчуванням, коли ви
виводите

Але що робити, якщо рядок може містити int або float?
GeneCode

179

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


27
+ q Залежно від ситуації, не чутливий до локальної локалізації може бути правильним.
Тило

2
Мені довелося перетворитись @"2000"на intта [@"2000" integerValue]добре працював, і це трохи простіше для мого випадку.
Бесі

2
Серед цих методів також існують величезні відмінності в роботі.
Том Андерсен

2
це не працює з ARC: він не перетворить NSInteger в NSNumber. Мені потрібно додатково використовувати[NSNumber numberWithInteger ...]
учень

Що сказав @Thilo "Правильний" та "чутливий до локальних" не є синонімами. Правильна річ насправді залежить від того, як число потрапило в рядок в першу чергу. Якщо ви читаєте це з введення користувача, то чутливий до локального - це те, що вам потрібно. З будь-якого іншого джерела (тобто ви розміщуєте його там програмно, ви вживаєте його як частину відповіді з якогось зовнішнього API тощо), чутливий до місцевих відносин не підходить і навіть може дати невірні результати.
aroth

138

Ціль-С

(Примітка: цей метод не грає добре з різницею локалів, але трохи швидший, ніж a 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

1
Я вважаю за краще це на основі профілювання, коли я розбирав велику кількість рядкових значень. Використання цього синтаксису, а не NSNumberFormatter призвело до значного скорочення часу, витраченого на аналіз рядка на NSNumber. І так, NSNumberFormatter був кешований і повторно використаний.
androider

3
цього буквального синтаксису не було, коли це питання було задано. Я б сказав, що це правильна відповідь, хоча сьогодні.
Кріс

1
Я погоджуюся, але зауважте, що деякі інші країни використовують ,і .навпаки (наприклад, 42.000,42чогось, floatValueмабуть, не враховують?
Kevin R

1
Це найкраще рішення тут, однак я тільки що провів тест, і ви втратите непідписану точність, тому ПОДІЛИТИ !!!
Stoff81

У моєму випадку використання мені потрібно було отримати ключ словника NSNumber від NSString, який @([@"42" intValue])працював чудово. Не переживає Локаль.
Чак Крутсінгер

86

Для рядків , що починаються з цілими числами, наприклад, @"123", @"456 ft", @"7.89"і т.д., використання -[NSString integerValue].

Отже, @([@"12.8 lbs" integerValue])це як робити [NSNumber numberWithInteger:12].


50

Ви також можете зробити це:

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

Веселіться!


26

Якщо ви знаєте, що отримуєте цілі числа, ви можете використовувати:

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

11

Ось робочий зразок читання 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

це не працює для мене. Я розробляю для 5.0 з xcode 4.3.2. будь-які ідеї чому?
acecapades


5

Дякую всім! Мене поєднують зворотний зв'язок і, нарешті, вдається перетворити текст із введення тексту (рядка) в цілий. Плюс це може сказати мені, чи є вхід цілим числом :)

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

Я думаю, що NSDecimalNumber зробить це:

Приклад:

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

NSDecimalNumber - це підклас NSNumber, тому допускається неявна трансляція.


2

А як щодо стандарту С atoi?

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

Як ви думаєте, чи є якісь застереження?



2

Ви також можете зробити цей код, як підтримка 8.3.3 ios 10.3

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



0

Я знаю, що це дуже пізно, але нижче код працює для мене.

Спробуйте цей код

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

Це може вам допомогти. Дякую


0

Спробуйте це

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

Примітка - я використовував longLongValue відповідно до моєї вимоги. Ви також можете використовувати integerValue, longValue або будь-який інший формат залежно від вашої вимоги.


-1
extension String {

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

let someFloat = "12.34".numberValue
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.