将NSTextField绑定到NSNumber

时间:2009-02-09 07:11:51

标签: cocoa interface-builder

我正在尝试使用NSTextField进行整数用户输入。文本字段绑定到NSNumber属性,在setter方法中我清理输入值(确保它是一个int)并在必要时设置属性。我发送了willChangeValueForKey:和didChangeValueForKey:,但是当该文本字段仍处于活动状态时,UI不会更新为新值。

例如,我可以在文本字段中键入“12abc”,setter方法清除“12”,但文本字段仍显示“12abc”。

我在界面构建器中选中了“连续更新值”。

(我也注意到setter方法接收的是NSString,而不是NSNumber。这是正常的吗?)

将NSTextField连接到NSNumber的正确方法是什么?该属性的setter方法是什么样的?如何防止非数字值出现在文本字段中?

4 个答案:

答案 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,因为它非常明显是为此目的而设计的类。

More about value transformers

答案 3 :(得分:0)

我认为您需要为NSTextField设置一个数字格式化程序。

在Apple的网站上阅读有关格式化程序的信息:Applying Formatters