我想要一个需要接受一些用户输入的窗口,为此我有以下内容:
NSWindow
从带有NSWindowController
的nib加载,也是其委托NSTextField
的一对NSNumberFormatter
NSTextField
绑定到NSWindowController
中的整数属性(为简单起见,我没有使用NSObjectController
,但可以根据需要添加它)NSButton
windowShouldClose:
方法中进行最终验证并决定是否可以关闭窗口我想要实现的目标非常简单,但Cocoa坚持要做到这一点具有挑战性:
NSTextField
只接受一个数字作为最终值,也就是大于零足够简单。 NSNumberFormatter应该已经涵盖了大部分任务,并且与绑定一起,这应该很容易实现。
问题#1:
我无法找到一种方法来更改在NSTextField
失去焦点时更改警告中向用户显示的错误消息,并且该值对于更具描述性的内容不正确。有没有办法做到这一点?或者我需要以某种方式实现我自己的NSFormatter?
问题#2:
当用户更改NSTextField
中的值并单击“完成”按钮时,Cocoa不会将此视为更新模型NSTextField
绑定的值的触发器。这可能是标准的OSX行为,但是没有任何意义。
我能够通过在“完成”按钮的操作中调用[window makeFirstResponder:nil]
来强制NSTextField
失去焦点并更新值,但我想知道这是否是正确的方法实现这一目标。
问题#3:
这就是我真正挠头的地方。如果用户在NSTextField
中输入了错误的值(如非整数)并单击“完成”按钮,则验证不会启动,NSTextField
将继续使用不正确的值没有更新。
我希望仍会显示“无效”警告,并且我有一些地方可以插入代码来决定是否关闭窗口,但我找不到任何方法来覆盖此行为。< / p>
达到这些要求的标准做法应该是什么?我是否应该放弃格式化程序和/或绑定,并使用操作手动完成所有操作?
答案 0 :(得分:1)
对于问题1,请尝试为文本字段设置委托并实施-control:didFailToFormatString:errorDescription:
和-control:didFailToValidatePartialString:errorDescription:
。提供您想要的任何UI,或者使用错误描述。
或者,您可以实现NSNumberFormatter
的自定义子类并覆盖-getObjectValue:forString:errorDescription:
和-isPartialStringValid:proposedSelectedRange:originalString:originalSelectedRange:errorDescription:
。您可以通过super调用大部分实现。如果失败,您可以替换超级提供的错误描述。如果您需要格式化程序对象的上下文(其属性等)以找出更好的错误描述,则可以使用此方法。
问题2的正确解决方案是不以编程方式更改第一响应者。相反,您确实应该使用NSObjectController
在文本字段和窗口控制器之间进行调解。在“完成”按钮的操作方法中,调用-commitEditing
或-commitEditingWithDelegate:didCommitSelector:contextInfo:
。 NSObjectController
从NSController
继承了那些采用NSEditor
协议的方法。当您获得结果(同步为前者,后者为异步)时,您可以继续执行或不执行任何操作,具体取决于提交是成功还是失败。
我怀疑问题3也是以编程方式更改窗口的第一响应者的结果。通常情况下,程序化更改不会受到与用户操作所做的相应更改相同的检查。框架假设您,程序员知道您正在做什么,因此将编程更改重点放在格式化程序的验证上是“错误的”,例如。