我正在尝试使用NSTextField进行整数用户输入。文本字段绑定到NSNumber属性,在setter方法中我清理输入值(确保它是一个int)并在必要时设置属性。我发送了willChangeValueForKey:和didChangeValueForKey:,但是当该文本字段仍处于活动状态时,UI不会更新为新值。
例如,我可以在文本字段中键入“12abc”,setter方法清除“12”,但文本字段仍显示“12abc”。
我在界面构建器中选中了“连续更新值”。
(我也注意到setter方法接收的是NSString,而不是NSNumber。这是正常的吗?)
将NSTextField连接到NSNumber的正确方法是什么?该属性的setter方法是什么样的?如何防止非数字值出现在文本字段中?
答案 0 :(得分:10)
我发送了willChangeValueForKey:和didChangeValueForKey :,但是当该文本字段仍处于活动状态时,UI不会更新为新值。
发送这些消息的理由很少。通常,通过实现和使用访问器(或者更好的属性),您可以更好,更干净地完成相同的工作。当你这样做时,KVO会为你发送通知。
在您的情况下,您要拒绝或过滤虚假输入(如“12abc”)。此任务的正确工具是键值验证。
要启用此功能,请检查IB中绑定的“立即验证”框,并实施验证方法。
过滤
- (BOOL) validateMyValue:(inout NSString **)newValue error:(out NSError **)outError {
NSString *salvagedNumericPart;
//Determine whether you can salvage a numeric part from the string; in your example, that would be “12”, chopping off the “abc”.
*newValue = salvagedNumericPart; //@"12"
return (salvagedNumericPart != nil);
}
拒绝:
- (BOOL) validateMyValue:(inout NSString **)newValue error:(out NSError **)outError {
BOOL isEntirelyNumeric;
//Determine whether the whole string (perhaps after stripping whitespace) is a number. If not, reject it outright.
if (isEntirelyNumeric) {
//The input was @"12", or it was @" 12 " or something and you stripped the whitespace from it, so *newValue is @"12".
return YES;
} else {
if (outError) {
*outError = [NSError errorWithDomain:NSCocoaErrorDomain code: NSKeyValueValidationError userInfo:nil];
}
//Note: No need to set *newValue here.
return NO;
}
}
(我也注意到setter方法接收的是NSString,而不是NSNumber。这是正常的吗?)
是的,除非您使用将字符串转换为数字的值转换器,请将数字格式器连接到formatter
插座,或者在验证方法中用NSNumber替换NSString。
答案 1 :(得分:2)
对Peter Hosey的优秀答案有一个重要评论,我想提升到最高级别(因为我在第一次通过时错过了它)。
如果您想在每次输入字符时验证/修改NSTextField,而不是仅在用户提交字段时验证/修改NSTextField,那么您无法单独从绑定中获得所需内容。您需要将委托分配给文本字段,然后在委托中实现- (void)controlTextDidChange:(NSNotification *)aNotification
。每次文本更改时都会调用此方法。如果需要,可以在controlTextDidChange
中调用值验证器。
例如:
- (void)controlTextDidChange:(NSNotification *)aNotification
{
NSError *outError;
NSControl *textField = [aNotification object];
NSString *myText = [textField stringValue];
// myObject is the model object that owns the text in question
// the validator can modify myText by reference
[myObject validateValue:&myText error:&outError]];
// update the NSNextField with the validated text
[postingObject setStringValue:myText];
}
答案 2 :(得分:1)
像Ben提到的那样,一种方法是将NSNumberFormatter附加到文本字段,这在界面构建器中设置非常简单,并且可能是Just Work™。
如果您不喜欢NSNumberFormatter在输入非数字值时向用户抛出的模态对话框,则可以将NSNumberFormatter子类化以实现不同的“更宽容”格式化行为。我认为重写 - numberFromString:在调用super的实现之前删除非数字字符应该可以解决问题。
另一种方法是创建并注册自己的NSValueTransformer子类,将字符串解析为NSNumbers并返回,但我首先尝试使用NSNumberFormatter,因为它非常明显是为此目的而设计的类。
答案 3 :(得分:0)
我认为您需要为NSTextField
设置一个数字格式化程序。
在Apple的网站上阅读有关格式化程序的信息:Applying Formatters。