views:

202

answers:

1

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.

+1  A: 

Firstly, i think the text is selected because calling selectItemAtIndex: has made the comboBox the firstResponder. You could use setRefusesFirstResponder: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.

mustISignUp
THANKS for this! See my follow-up response above, as an edit to the question.
Dennis
I don't have an answer really, but if you are not using FScript to help you with things like this you will definitely want to. Put the FScript framework in Library/Frameworks, link against it. Add [[NSApp mainMenu] addItem:[[FScriptMenuItem alloc] init]]; to -applicationDidFinishLaunching. Start your app and check out the FScript menuItem. From the menu launch a 'browser for view' you can now select your window, view, or combo box and try sending messages to it. It is invaluable for stuff like this.
mustISignUp
Looks awesome. Thanks for this pointer.
Dennis