Search code examples
iphoneobjective-cios4nsnumberformatterios32

NSNumberFormatter iOS 3.2 Bug?


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

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


Solution

  • 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];