将NSTextField输入限制为仅限数字? NSNumberformatter

时间:2011-01-10 23:24:15

标签: objective-c cocoa macos nstextfield

我刚刚开始使用Mac App Development,到目前为止一切都很好,我只是在尝试让NSTextField只接受输入数字时遇到问题。

到目前为止,我已经向NSTextField添加了一个格式化程序并将其设置为仅允许小数现在当我在字段中输入字母时它仍然允许我但是不允许我在完成时单击单元格。

理想情况下,我希望应用不要让用户输入任何字母,只是发出嘟嘟声或什么都不做。

关于此的任何提示或指示都会很棒

5 个答案:

答案 0 :(得分:8)

子类NSNumberFormatter并实现此方法:

- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
       proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
              originalString:(NSString *)origString
       originalSelectedRange:(NSRange)origSelRange
            errorDescription:(NSString **)error

答案 1 :(得分:3)

以下是创建相同步骤的步骤:

只需创建ANYCLASS(称为SAMPLE)子类化NSNumberFormatter,并在.m文件中编写以下代码...

     (BOOL)isPartialStringValid:(NSString *)partialString newEditingString:(NSString **)newString errorDescription:(NSString **) error {
    // Make sure we clear newString and error to ensure old values aren't being used
    if (newString) { *newString = nil;}
    if (error)     {*error = nil;}

    static NSCharacterSet *nonDecimalCharacters = nil;
    if (nonDecimalCharacters == nil) {
        nonDecimalCharacters = [[NSCharacterSet decimalDigitCharacterSet] invertedSet] ;
    }

    if ([partialString length] == 0) {
        return YES; // The empty string is okay (the user might just be deleting everything and starting over)
    } else if ([partialString rangeOfCharacterFromSet:nonDecimalCharacters].location != NSNotFound) {
        return NO; // Non-decimal characters aren't cool!
    }

    return YES;
}

现在,在您的Actual Class中,将格式化程序设置为NSTextField对象,如下所示:

NSTextField *mySampleTxtFld;

为此设置Formatter:

SAMPLE* formatter=[[SAMPLE alloc]init]; // create SAMPLE FORMATTER OBJECT 

self.mySampleTxtFld.delegate=self;
[self.mySampleTxtFld setFormatter:formatter];

你已经完成了!

答案 2 :(得分:2)

这是另一种实现方式:

+ (BOOL)stringIsNumber:(NSString *)str {
   BOOL valid;
   double holder;
   NSScanner *scan = [NSScanner scannerWithString: str];
   valid = [scan scanDouble:&holder] && [scan isAtEnd];
  return valid;
}

+ (NSString *)numericStringFromString:(NSString *)string {
    NSString *digitsString = string;
    if (![YOURCLASSNAME stringIsNumber:string]) {
        NSUInteger length = [string length];
        if (length > 0) {
            digitsString = [string substringToIndex:length - 1];
            if (![YOURCLASSNAME stringIsNumber:digitsString]) {
                digitsString = [YOURCLASSNAME numericStringFromString:digitsString];
            }
        }
    }
    return digitsString;
}

然后在我的控制器类中,我实现了controlTextDidChange:

- (void)controlTextDidChange:(NSNotification *)obj {
   NSString *digitsString = [YOURCLASSNAME numericStringFromString:self.currentCellView.textField.stringValue];
   if (digitsString) {
    self.currentCellView.textField.stringValue = digitsString;
   } else {
    self.currentCellView.textField.stringValue = @"";
   }
}

这种方法的好处是,如果您将文本粘贴到数字字段中,这将从字符串末尾删除所有非数字字符,直到您只剩下一个数字。此外,它支持任意长的数字系列。其他一些方法不支持输入一系列无法​​在NSInteger中保存的数字。

我知道这种方法当然可以改进。

答案 3 :(得分:1)

您可以在视图控制器中使用NSControlTextEditingDelegate方法,而不是子类化任何内容。设置要检查的delegate的{​​{1}}字段,然后在NSTextField函数中执行以下操作,在每个键入的字符上调用该函数。在这种情况下,不要忘记初始化controlTextDidChange:。此函数使用self.lastValidTimestampCount检查值,其中可能包含逗号。

RegExLite

答案 4 :(得分:1)

NPAssoc的答案对我有帮助,我对没有使用isMatchedByRegex函数的代码做了一些改动。

// Make sure the user has typed a valid number so far.
- (void)controlTextDidChange:(NSNotification *)obj
{
    if (obj.object == self->number)
    {
        NSString *countValue = number.stringValue;        
        if ([countValue length] > 0) {
            if ([[countValue substringFromIndex:[countValue length]-1] integerValue] > 0 ||
                [[countValue substringFromIndex:[countValue length]-1] isEqualToString:@"0"])
            {
                self.lastNumber = number.stringValue;
            }
            else
            {
                number.stringValue = self.lastNumber;
                NSBeep();
            }
        }
    }
}

PS:使用[self setIntValue:[self intValue]]限制输入的长度。