开发者

NSNumberFormatter iOS 3.2 Bug?

开发者 https://www.devze.com 2023-01-23 04:26 出处:网络
I have code that I am porting from iOS 4 to iOS 3.2 for a demo project on an iPad. I have this code: +(int) parseInt:(NSString *)str

I have code that I am porting from iOS 4 to iOS 3.2 for a demo project on an iPad. I have this code:

+(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];
    }
}

This works spendid on iOS 4, throwing exceptions when a string (such as a date, which I am having problems with): 1/1/2010

For some reason, num isn't nil, it has the value 1, while on iOS 4, It is nil as expected. I was originally using NSScanner because it was easier than NSNumberFormatter to use, but I ran into the same problem, it doesn't parse the entire string, just the first number in the string.

Is there something I can do to fix this, or must I manually create an int parser. I would prefer not to use a C-Based approach, but if I must, I will.

EDIT: I have updated my code to this:

+(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 e开发者_Python百科xceptionWithDescription:@"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];
    }
}

And I get a EXC_BAD_ACCESS signal when I try to parse the string 1/1/2001. Any Ideas? (iOS 4 or greater is defined here: http://cocoawithlove.com/2010/07/tips-tricks-for-conditional-ios3-ios32.html)

I have a new error: when I parse the number, it isn't exact (exact as in it has multiple decimal points when using same code for floats) anymore.... how can I fix that?? (I might just use @joshpaul's answer...)


I couldn't find anything specific to iOS but the data formatting guide has this interesting paragraph:

Note: Prior to Mac OS v10.6, the implementation of getObjectValue:forString:errorDescription: would return YES and an object value even if only part of the string could be parsed. This is problematic because you cannot be sure what portion of the string was parsed. For applications linked on or after Mac OS v10.6, this method instead returns an error if part of the string cannot be parsed. You can use getObjectValue:forString:range:error: to get the old behavior; this method returns the range of the substring that was successfully parsed.

I would not be at all surprised if numberFromString: was implemented in terms of the above method and the iOS 3.2 NSNumberFormatter is based on 10.5 whereas the iOS 4 version is 10.6.

Just my guess.

If you pass 1/1/2010 on iOS 3.2 the 1 will be parsed and the rest ignored. You could test the hypothesis by seeing if you get 2 when you pass 2/1/2010.

The work around would seem to be to use getObjectValue:forString:range:error:.


So the basic [str intValue] doesn't work? Nor, [scanner scanInt:&int]?

What about using NSCharacterSet, i.e.:

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号