【问题标题】:NSNumberFormatter iOS 3.2 Bug?NSNumberFormatter iOS 3.2 错误?
【发布时间】:2010-11-03 23:29:12
【问题描述】:

我有代码要从 iOS 4 移植到 iOS 3.2,用于 iPad 上的演示项目。我有这个代码:

+(int) parseInt:(NSString *)str
{
    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
    [nf setAllowsFloats:NO];
    [nf setMaximum:[NSNumber numberWithInt:INT_MAX]];
    [nf setMinimum:[NSNumber numberWithInt:INT_MIN]];

    @try {
        NSNumber *num = [nf numberFromString:str];
        if (!num)
            @throw [DataParseException exceptionWithDescription:@"the data is not in the correct format."]; 

        return [num intValue];
    }
    @finally {
        [nf release];
    }
}

这适用于 iOS 4,当字符串(例如日期,我遇到问题)时抛出异常: 1/1/2010

由于某种原因,num 不是 nil,它的值是 1,而在 iOS 4 上,它是 nil,正如预期的那样。我最初使用NSScanner,因为它比NSNumberFormatter 更容易使用,但我遇到了同样的问题,它不解析整个字符串,只解析字符串中的第一个数字。

我可以做些什么来解决这个问题,或者我必须手动创建一个 int 解析器。我不希望使用基于 C 的方法,但如果必须,我会这样做。

编辑:我已将我的代码更新为:

+(int) parseInt:(NSString *)str
{
    NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
    [nf setAllowsFloats:NO];
    [nf setMaximum:[NSNumber numberWithInt:INT_MAX]];
    [nf setMinimum:[NSNumber numberWithInt:INT_MIN]];

    @try {
        IF_IOS4_OR_GREATER
        (
                NSNumber *num = [nf numberFromString:str];
            if (!num)
                @throw [DataParseException exceptionWithDescription:@"the data is not in the correct format."]; 

            return [num intValue];
        )
        else {
            NSNumber *num = nil;
            NSRange range = NSMakeRange(0, str.length);
            NSError *err = nil;
            [nf getObjectValue:&num forString:str range:&range error:&err];
            if (err)
                @throw [DataParseException exceptionWithDescription:[err description]];
            if (range.length != [str length])
                @throw [DataParseException exceptionWithDescription:@"Not all of the number is a string!"];
            if (!num)
                @throw [DataParseException exceptionWithDescription:@"the data is not in the correct format."]; 

            return [num intValue];
        }
    }
    @finally {
        [nf release];
    }
}

当我尝试解析字符串 1/1/2001 时,我收到了 EXC_BAD_ACCESS 信号。有任何想法吗? (此处定义了 iOS 4 或更高版本:http://cocoawithlove.com/2010/07/tips-tricks-for-conditional-ios3-ios32.html

我有一个新错误:当我解析数字时,它不准确(就像在使用相同的浮点数代码时它有多个小数点一样)......我该如何解决这个问题? (我可能只是使用@joshpaul 的答案...)

【问题讨论】:

  • 你真的不应该为此使用异常。 obj-c 中的异常旨在表示程序员错误。数据错误,例如这个错误,应该使用基于 NSError* 的 API。
  • 对不起,我和我的老板有一个问题,nils 只是在代码中运行 arround...
  • @Kevin Ballard:使用此 API 无法指示错误值,因为任何 int 都是有效的。
  • @JeremyP:我想到了几个解决方案。第一种是只返回 NSNumber* 并让调用者在其上调用 -intValue。第二个是保证一个有效的调用总是将错误参数归零,并声明返回值为 0 意味着调用者需要检查参数。第三种方法是返回 BOOL 并在 out 参数中返回 int。

标签: iphone objective-c ios4 nsnumberformatter ios32


【解决方案1】:

我找不到任何特定于 iOS 的内容,但 data formatting guide 有这个有趣的段落:

注意:在 Mac OS v10.6 之前,getObjectValue:forString:errorDescription: 的实现将返回 YES 和一个对象值即使只能解析部分字符串。这是有问题的,因为您无法确定字符串的哪一部分已被解析。对于在 Mac OS v10.6 上或之后链接的应用程序,如果无法解析部分字符串,则此方法会返回错误。您可以使用getObjectValue:forString:range:error: 来获取旧行为;该方法返回成功解析的子串的范围。

如果numberFromString:是按照上述方法实现的,并且iOS 3.2 NSNumberFormatter是基于10.5,而iOS 4版本是10.6,我一点也不会感到惊讶。

只是我的猜测。

如果您在 iOS 3.2 上通过 2010 年 1 月 1 日,则 1 将被解析,其余的将被忽略。您可以通过 2010 年 2 月 1 日是否得到 2 来检验假设。

解决方法似乎是使用getObjectValue:forString:range:error:

【讨论】:

  • 为什么不能只是一个简单的int.Parse() 电话:)
  • @Richard J. Ross III:你可以看看NSDecimalNumber decimalNumberWithString:
【解决方案2】:

所以基本的[str intValue] 不起作用?也不是[scanner scanInt:&int]?

如何使用NSCharacterSet,即:

NSString *test = [str stringByTrimmingCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]];
if ([test length]) @throw ...;
return [str intValue];

【讨论】:

  • 一个有趣的解决方案....我不知道这对我来说是否实用..我会尝试@JeremyP 写的内容,然后再看看你的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 2014-01-08
  • 1970-01-01
相关资源
最近更新 更多