如何将NSString转换为NSNumber

581

我该如何将包含任何基本数据类型(例如 intfloatcharunsigned int 等)的 NSString 转换为相应的数字类型?问题是,我不知道字符串在运行时包含哪种数字类型。

我有一个想法,但我不确定是否适用于任何类型,包括无符号和浮点数值:

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

感谢您的帮助。

18个回答

1267

使用NSNumberFormatter

NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
f.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber *myNumber = [f numberFromString:@"42"];
如果该字符串不是有效的数字,则myNumber将为nil。如果是有效数字,则现在可以使用所有NSNumber所提供的功能来确定它实际上是什么类型的数字。

16
对于似乎无效的人:检查是否与您的区域设置有关。NSNumberFormatter(据我所知)默认使用美国区域设置,即期望小数分隔符为“.”字符。如果您使用“,”来分隔小数部分,则可能需要告诉格式化程序使用当前的区域设置:[f setLocale:[NSLocale currentLocale]]; - pille
3
@pille 默认情况下,区域设置是+currentLocale,但你说得对;在处理将东西转换为人类可读形式时,必须始终考虑区域设置。 - Dave DeLong
你从哪里得知默认是currentLocale? 我可以确认,即使在法国手机上使用逗号,numberFromString也使用点符号表示小数。 我可以确认,默认情况下,在输出数字时它使用当前语言环境。 - allaire
但如果字符串可能包含整数或浮点数呢? - GeneCode

183
您可以使用-[NSString integerValue]-[NSString floatValue]等方法。然而,进行正确的转换(考虑到本地化等因素)应该使用-[NSNumberFormatter numberFromString:] 方法,该方法将根据NSNumberFormatter的设置(包括是否允许浮点数值)从适当的本地环境中转换为NSNumber类型。请注意保留原有的HTML标签格式。

27
根据情况,非本地化敏感可能是正确的方式。 - Thilo
2
我需要将 @"2000" 转换为 int,而 [@"2000" integerValue] 很好地解决了我的问题,并且对于我的情况来说更简单。 - Besi
2
这些方法之间也存在巨大的性能差异。 - Tom Andersen
2
这在ARC下不起作用:它无法将NSInteger转换为NSNumber。我必须进一步使用[NSNumber numberWithInteger ...] - learner
@Thilo所说的是对的。“正确”和“区域敏感”不是同义词。实际上,正确的做法取决于数字最初是如何进入字符串的。如果您从用户输入中读取它,则需要使用区域敏感。从任何其他来源(即您以编程方式放置它,将其作为某些外部API响应的一部分进行消耗等)都不适用于区域敏感,甚至可能会导致错误的结果。 - aroth

147

Objective-C

(注:此方法与不同地区的语言环境兼容性不佳,但比 NSNumberFormatter 稍微快些。)

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

Swift

简单但不太优雅的方法

// 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 = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter.number(from: self)
    }
}

现在你可以简单地执行:

let someFloat = "42.42".numberValue
let someInt = "42".numberValue

1
在解析大量字符串值时,我更喜欢使用基于分析的方法。与NSNumberFormatter相比,使用这种语法可以显著减少将字符串解析为NSNumber所花费的时间。是的,NSNumberFormatter已被缓存和重复使用。 - androider
3
当这个问题被问出来的时候,这种文字语法并不存在。不过现在来看,我认为这是正确的答案。请注意,这句话只是翻译,没有解释或者其他额外内容返回。 - Chris
1
我同意,但请注意一些其他国家使用逗号和句点相反的方式(例如:42.000,42)。这可能是floatValue无法考虑到的事情。 - Kevin R
1
这是这里最好的解决方案,但我刚刚进行了测试,你会失去无符号精度,所以小心!!! - Stoff81
在我的使用情况中,我需要从NSString获取一个NSNumber字典键,因此@([@"42" intValue])非常完美。不用担心Locale。 - Chuck Krutsinger

87
对于以整数开头的字符串,例如@"123"@"456 ft"@"7.89"等,使用-[NSString integerValue]方法。
因此,@([@"12.8 lbs" integerValue])就像执行[NSNumber numberWithInteger:12]一样。

51
你还可以这样做:
NSNumber *number = @([dictionary[@"id"] intValue]]);

玩得开心!


该方法不会将所有数字转换,例如123,45。只会转换123。 - yasin89

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

这对我没用。我正在使用Xcode 4.3.2开发5.0版本。有什么想法为什么会这样? - 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];

5

我想将一个字符串转换成双精度浮点数。上面的答案对我来说并不完全适用。但是这个链接中的方法适用:如何在Objective-C中进行字符串转换?

基本上我所做的就是:

double myDouble = [myString doubleValue];

这并不会将 NSInteger 转换为 NSNumber。它将其转换为 double。 - FabKremer

4
我认为NSDecimalNumber可以实现这个功能:
举个例子:
NSNumber *theNumber = [NSDecimalNumber decimalNumberWithString:[stringVariable text]]];

NSDecimalNumber是NSNumber的子类,因此允许隐式转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接