Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Restrict NSTextField to only allow numbers

How do I restrict a NSTextField to allow only numbers/integers? I've found questions like this one, but they didn't help!

like image 355
JomanJi Avatar asked Aug 28 '12 14:08

JomanJi


5 Answers

Try to make your own NSNumberFormatter subclass and check the input value in -isPartialStringValid:newEditingString:errorDescription: method.

@interface OnlyIntegerValueFormatter : NSNumberFormatter

@end

@implementation OnlyIntegerValueFormatter

- (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])) {
        NSBeep();
        return NO;
    }

    return YES;
}

@end

And then set this formatter to your NSTextField:

OnlyIntegerValueFormatter *formatter = [[[OnlyIntegerValueFormatter alloc] init] autorelease];
[textField setFormatter:formatter];
like image 158
Dmitry Avatar answered Nov 10 '22 08:11

Dmitry


Swift 3 Version

import Foundation

    class OnlyIntegerValueFormatter: NumberFormatter {

    override func isPartialStringValid(_ partialString: String, newEditingString newString: AutoreleasingUnsafeMutablePointer<NSString?>?, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {

        // Ability to reset your field (otherwise you can't delete the content)
        // You can check if the field is empty later
        if partialString.isEmpty {
            return true
        }

        // Optional: limit input length
        /*
        if partialString.characters.count>3 {
            return false
        }
        */

        // Actual check
        return Int(partialString) != nil
    }
}

Use:

let onlyIntFormatter = OnlyIntegerValueFormatter()
myNsTextField.formatter = onlyIntFormatter
like image 28
Xavier Daleau Avatar answered Nov 10 '22 07:11

Xavier Daleau


Here's a solution with filtering. Give a delegate and an outlet to textfield and set controlTextDidChange method.

- (void)controlTextDidChange:(NSNotification *)aNotification {

    NSTextField *textfield = [notification object];
    NSCharacterSet *charSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];

    char *stringResult = malloc([textfield.stringValue length]);
    int cpt=0;
    for (int i = 0; i < [textfield.stringValue length]; i++) {
        unichar c = [textfield.stringValue characterAtIndex:i];
        if ([charSet characterIsMember:c]) {
            stringResult[cpt]=c;
            cpt++;
        }
    }
    stringResult[cpt]='\0';
    textfield.stringValue = [NSString stringWithUTF8String:stringResult];
    free(stringResult);
}
like image 9
Luc-Olivier Avatar answered Nov 10 '22 08:11

Luc-Olivier


Try this -

NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[textField setFormatter:formatter];
like image 8
Slavcho Avatar answered Nov 10 '22 09:11

Slavcho


Here is a Swift version:

override func isPartialStringValid(partialString: String, newEditingString newString: AutoreleasingUnsafeMutablePointer<NSString?>, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>) -> Bool {
    if (count(partialString.utf16)) {
        return true
    }

    if (partialString.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet) != nil) {
        NSBeep()
        return false
    }

    return true
}
like image 4
rdougan Avatar answered Nov 10 '22 08:11

rdougan