如何通过KVC设置NSComboBox的值?
我在 Interface Builder 中创建了几个 NSComboBox,其中一个是以编程方式创建的。
Interface Builder 中创建的 NSComboBox 非常完美。我将它们的值绑定到共享用户默认控制器,当它们的视图打开时,它们就坐在那里并具有正确的值。重要的是,该值在 NSComboBox 中显示为“正常”文本。换句话说,该值并未显示为已选择。这就是我想要的。
对于以编程方式创建的 NSComboBox,我使用 selectItemAtIndex:0 设置值。当我这样做时,会选择正确的项目 - 但文本似乎被选中。即,它被突出显示和一切。我不想要这个。以下是我尝试过的解决方法:
(i) 获取字段编辑器并将插入点设置到文本末尾。这不起作用,但奇怪的是,执行此操作时字段编辑器的字符串要么为零或为空。我不确定这对于字段编辑器来说是否是正确的行为。
(ii) 尝试设置组合框值的各种其他方法,例如 setObjectValue、takeStringValueFrom 等。
(iii) 最后,最令人沮丧的是,我尝试使用 [myComboBox setValue:@"The Default Item] 设置 NSComboBox 的值" forKey:@"值"];这会失败并出现 objc_exception_throw,大概是因为没有这样的 KVC 密钥。但我知道组合框的值可以通过 KVO 设置,因为它在界面生成器中工作!我猜我不知道正确的关键路径。我尝试使用内省枚举所有属性,但我无法使代码正常工作(objc_property_t 不在预期的标头中)。
所以,我有两个问题:
首先,有谁知道如何以编程方式设置 NSComboBox 的默认值,以便不选择框中的文本?我将不遗余力地做到这一点,包括一个新的 NSComboBoxCell 子类(如果涉及到的话)。
其次,有人可以告诉我 IB 使用什么键或键路径来设置 NSComboBox 的值吗?或者说,为什么我的努力却失败了?
我已经为此工作了好几个小时了,我真的很沮丧!
谢谢,必须注册!很高兴解决这个问题。一点后续:
(i)文本的选择肯定是由焦点引起的。调用 setRefusesFirstResponder:YES 可以解决该问题。不幸的是,窗口确实想要专注于这个组合框,因为将拒绝FirstResponder设置回NO(稍后,在窗口启动之后)会再次导致文本选择(我确实希望用户能够根据需要专注于这个框)。因此,就我而言,最终的解决方案是调用 [window makeFirstResponder:otherControl]。奇怪的是,尽管 [window makeFirstResponder:nil] 不起作用。有什么想法吗?
(ii) 感谢您指出绑定和属性之间的区别。在研究这个问题时我学到了很多东西。首先,我了解到您可以通过调用 - (NSArray *)exposeBindings 来获取绑定列表,对于 NSComboBox 返回 (fontSize、alignment、toolTip、fontName、enabled、contentValues、fontFamilyName、font、hidden、fontItalic、textColor、value ,内容,可编辑,字体粗体)。其次,我能够使用 [myComboBox bind:@"value" toObject:[NSMutableString stringWithString:@"defaultValue"] withKeyPath:@"string" options:nil] 设置值,其中 NSMutableString 上有一个类别,可以将“字符串”到属性中。最后,这实际上并不能解决文本选择“问题”。使用此组合框和 Interface Builder 中的文本选择之间的区别必须是它们在窗口中的位置...我猜想此组合框将成为 initialFirstResponder,而其他组合框则不会。
所以我唯一剩下的问题可能是为什么 [window makeFirstResponder:nil] 无法将焦点从组合框上移开。不是非常重要,但我很好奇是否有人有想法。
I have several NSComboBoxes created in Interface Builder, and one created programmatically.
The NSComboBoxes created in Interface Builder are perfect. I have their Value bound to the Shared User Default Controller, and when their view is opened they are sitting there with the correct value. Importantly, this value is shown as "normal" text in the NSComboBox. In other words, the value doesn't appear selected. This is what I want.
For the NSComboBox that is created programmatically, I set the value using selectItemAtIndex:0. When I do this, the correct item is selected--but the text appears selected. I.e., it is highlighted and everything. I don't want this. Here are the workarounds I've attempted:
(i) Get the field editor and set insertion point to the end of the text. This doesn't work although, oddly, the field editor's string is either nil or empty when doing this. I'm not sure if this is correct behavior for the field editor.
(ii) Trying various other ways of setting the combo box's value, such as setObjectValue, takeStringValueFrom, etc.
(iii) Finally, and most frustratingly, I tried to set the value of the NSComboBox using [myComboBox setValue:@"The Default Item" forKey:@"value"]; This fails with objc_exception_throw, presumably because there is no such KVC key. But I know that the value of the combo box can be set by KVO, because it works in interface builder! I'm guessing that I don't know the correct key path. I tried to enumerate all the properties using introspection, but I can't get the code working right (objc_property_t isn't in the expected headers).
So, I have two questions:
First, does anyone know how to set a default value for NSComboBox programmatically, so that the text in the box isn't selected? I will go to any lengths to do this, including a new NSComboBoxCell subclass, if it comes to that.
Second, can somebody tell me what key or key path IB is using to set the value of an NSComboBox? Or alternatively, why my efforts to do this are failing?
I've been working on this for many hours now and I am truly disspirited!
THANK YOU, mustISignUp! So nice to have this fixed. A little bit of followup:
(i) Selection of the text is definitely caused by focus. Calling setRefusesFirstResponder:YES fixes the problem. Unfortunately, the window really wants to focus on this combo box, as setting refusesFirstResponder back to NO (later, after window inititation) causes text selection again (I do want the user to be able to focus on this box if he desires). Therefore, in my case, the definitive solution was to call [window makeFirstResponder:otherControl]. Oddly, though [window makeFirstResponder:nil] doesn't work. Any ideas why?
(ii) Thanks for pointing out the difference between bindings and properties. I learned a lot while looking into this question. For one, I learned that you can get a list of bindings by calling - (NSArray *)exposedBindings, which for NSComboBox returns (fontSize, alignment, toolTip, fontName, enabled, contentValues, fontFamilyName, font, hidden, fontItalic, textColor, value, content, editable, fontBold). Second, I was able to set the value using [myComboBox bind:@"value" toObject:[NSMutableString stringWithString:@"defaultValue"] withKeyPath:@"string" options:nil], where NSMutableString has a category on it that turns "string" into a property. Finally, this actually doesn't fix the text selection "problem". The difference between text selection with this combo box and those in Interface Builder must be their position in the window...I guess that this combo box is just slated to become initialFirstResponder while the others weren't.
So my only remaining question might be why [window makeFirstResponder:nil] doesn't work to take focus off the combo box. Not super-important, but I'd be curious if anybody has an idea.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,我认为文本被选中是因为调用
selectItemAtIndex:
使组合框成为第一个响应者。您可以使用setRefusesFirstResponder:YES
或者您可以将另一个项目设置为第一响应者,以使文本不显示为选中状态。如果我理解正确并且您想更改组合框的选择,那么您的做法是正确的。
其次,您混淆了 Bindings 和 KVC。 NSComboBox 有一个名为“value”的绑定,而不是一个名为“value”的属性。尝试使用
setValue:forKey:
设置它是没有意义的,Interface Builder 肯定不会这样做。您认为这是不明显且令人困惑的,也许可以为绑定选择更好的名称,这是正确的。
Firstly, i think the text is selected because calling
selectItemAtIndex:
has made the comboBox the firstResponder. You could usesetRefusesFirstResponder:YES
or you could make another item the first responder to make the text not appear selected.If i have understood correctly and you want to change the selection of the comboBox you are doing it the right way.
Secondly, you are confusing Bindings and KVC. NSComboBox has a binding called 'value', not a property called 'value'. It is meaningless to try to set it with
setValue:forKey:
, and Interface Builder definitely isn't doing this.You would be right in thinking this is un-obvious and confusing and maybe better names could have been chosen for the bindings.