我刚刚开始使用 Mac App Development,到目前为止一切都很好,我只是在尝试让 NSTextField 只接受输入的数字时遇到问题。
到目前为止,我已经向 NSTextField 添加了一个格式化程序,并将其设置为现在只允许十进制,当我在字段中输入字母时它仍然允许我,但不允许我在完成后单击单元格。
理想情况下,我希望该应用程序不要让用户输入任何字母而只是发出哔哔声或什么也不做。
任何关于此的提示或指示都会很棒
我刚刚开始使用 Mac App Development,到目前为止一切都很好,我只是在尝试让 NSTextField 只接受输入的数字时遇到问题。
到目前为止,我已经向 NSTextField 添加了一个格式化程序,并将其设置为现在只允许十进制,当我在字段中输入字母时它仍然允许我,但不允许我在完成后单击单元格。
理想情况下,我希望该应用程序不要让用户输入任何字母而只是发出哔哔声或什么也不做。
任何关于此的提示或指示都会很棒
子类化NSNumberFormatter
并实现此方法:
- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
originalString:(NSString *)origString
originalSelectedRange:(NSRange)origSelRange
errorDescription:(NSString **)error
以下是创建相同的步骤:
只需创建子类化 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];
你完成了!
您可以使用NSControlTextEditingDelegate
视图控制器中的方法来实现,而不是继承任何东西。设置您要检查的delegate
字段,然后在每个键入的字符上调用的函数中执行以下操作。在这种情况下不要忘记初始化。此函数用于检查值,其中可能包含逗号。NSTextField
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;
}
}
这是一个替代实现:
+ (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 中的数字。
我知道这种方法当然可以改进。
NPAssoc's Answer 确实帮助了我,我对不使用 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]]限制输入的长度。