【问题标题】:Restrict NSTextField input to numeric only? NSNumberformatter将 NSTextField 输入限制为仅限数字? NSNumberformatter
【发布时间】:2011-01-10 23:24:14
【问题描述】:

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

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

理想情况下,我希望应用程序不要让用户输入任何字母,然后发出哔哔声或什么也不做。

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

【问题讨论】:

标签: objective-c cocoa macos nstextfield


【解决方案1】:

子类NSNumberFormatter并实现这个方法:

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

【讨论】:

  • 嗨你能解释一下我如何使用这个代码吗?理想情况下,我希望仅将输入限制为数字,逗号和小数除外,即用户可以输入 12.00 或 12,450
  • 你读过上面的文档吗?告诉我你不明白的地方
  • 感谢 Mike 的回复,我现在已经实现了一个自定义 NSFormatter,并且可以使用以下方法将文本限制为 10 个字符: if ([*partialStringPtr length] > maxLength) { 但是我仍然在努力解决我可以将输入限制为数字和一个小数点。很抱歉所有问题,因为你可以告诉我对这一切都很陌生。
  • 睡了个好觉后,我设法解决了这个问题,我现在正在使用您提到的子类,它能够检查是否允许输入以及是否已经存在小数位。跨度>
  • @FlankPlank 你能告诉我们更多关于你的解决方案吗?
【解决方案2】:

以下是创建相同的步骤:

只需创建子类化 NSNumberFormatter 的 ANYCLASS(称为 SAMPLE),然后在 .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;
}

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

NSTextField *mySampleTxtFld;

为此设置格式化程序:

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

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

你已经完成了!

【讨论】:

  • 这看起来是个不错的解决方案。
  • 很好的例子 - 真的很有帮助
【解决方案3】:

您可以在视图控制器中使用NSControlTextEditingDelegate 方法来实现,而不是继承任何东西。设置您要检查的NSTextFielddelegate 字段,然后在controlTextDidChange: 函数中执行以下操作,该函数会在每个键入的字符上调用。在这种情况下不要忘记初始化self.lastValidTimestampCount。此函数使用RegExLite 来检查值,其中可能包含逗号。

// Make sure the user has typed a valid number so far.
- (void)controlTextDidChange:(NSNotification *)obj
{
    if (obj.object == self.timestampsCount)
    {
        NSString *countValue = timestampsCount.stringValue;
        if (! [countValue isMatchedByRegex:@"^[\\d\\,]{1,6}$"])
        {
            timestampsCount.stringValue = self.lastValidTimestampCount;
            NSBeep();
        }
        else
            self.lastValidTimestampCount = timestampsCount.stringValue;
    }
}

【讨论】:

    【解决方案4】:

    这是一个替代实现:

    + (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 中的数字。

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

    【讨论】:

    • 完成....代替 Utilities 我们需要写我们的类名..为我工作...谢谢。
    • 抱歉,是的 Utilities 只是包含答案中提供的 numericStringFromString 方法的类。
    • 嘿,此代码正在限制数字,但是如果我只想输入 6 个数字怎么办.. 尝试使用您的代码... 没有解决方案.... 任何帮助???
    【解决方案5】:

    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]]限制了输入的长度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-14
      • 2013-08-21
      • 1970-01-01
      • 2020-12-01
      相关资源
      最近更新 更多