I'm using NSScanner to restrict a text field's value to numbers only, but I want to allow "-"

103 views Asked by At

I have an NSScanner in a custom NSNumberFormatter that scans for non-int values but I want it to skip "-" (dash)

- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error {
    if ([partialString length] == 0) {
        return YES;
    }
    
    NSScanner *scanner = [NSScanner scannerWithString:partialString];
    
    if (!([scanner scanInt:0] && [scanner isAtEnd])) {
        return NO;
    }
    
    return YES;
}

I thought I had to use [scanner charactersToBeSkipped] but I don't know how that works

2

There are 2 answers

0
YaYPIXXO On

I came up with my own solution. Each time a character is typed, it checks if the first one is a dash. If it is, it skips the first character and checks if the rest of the string contains ints. If the first character is not a dash, it scans the whole string for ints.

- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error {
    if ([partialString length] == 0) {
        return YES;
    }
    
    NSString *stringFromSecondChar;
    
    NSString *firstChar = [partialString substringToIndex:1];
    
    if ([partialString length] > 1 && [firstChar isEqualToString:@"-"]) {
        stringFromSecondChar = [partialString substringFromIndex:1];
    }
    else {
        stringFromSecondChar = partialString;
    }
    
    NSScanner *scanner = [NSScanner scannerWithString:stringFromSecondChar];
    
    if ([partialString length] == 1 && [firstChar isEqualToString:@"-"]) {
        return YES;
    }
    else if ([partialString length] >= 1 && [stringFromSecondChar containsString:@"-"]) {
        return NO;
    }
    
    if ([firstChar isEqualToString:@"-"]) {
        if (!([scanner scanInt:0] && [scanner isAtEnd])) {
            return NO;
        }
        else {
            return YES;
        }
    }
    
    if (!([scanner scanInt:0] && [scanner isAtEnd])) {
        return NO;
    }
    
    return YES;
}
0
Willeke On

Solution with regular expression:

- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error {
    if (partialString.length == 0)
        return YES;
    NSRange range = [partialString rangeOfString:@"^[-]?\\d*$" options:NSRegularExpressionSearch];
    return (range.location != NSNotFound);
}

Solution with NSScanner:

- (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **)error {
    if (partialString.length == 0 || [partialString isEqualToString:@"-"])
        return YES;
    NSScanner *scanner = [NSScanner scannerWithString:partialString];
    return ([scanner scanInt:NULL] && [scanner isAtEnd]);
}