multiple datasources for one combo box

Thanks ! I’ll research those methods ans see if can make heads or tails of them! :wink:

The way I’ve done this with tables, and the same should work for combo boxes or popup buttons, is to have one array that’s providing the content for the array controller (bind the array controller’s content array to this array, lets call it displayArray). You then bind the combo box/popup button’s content to the array controller with a Controller Key of arrangedObjects. Then, in code whenever you want to switch the content, you just redefine what displayArray is – so if you have array1, array2, etc. you can just have setDisplayArray_(array2). You’d probably want to blank what appears in the combo box’s text field, and maybe also deselect the selected item when you change arrays.

Ric

Would it be possible t put this in code please.

thanks,

Here’s an example with a popup button with three choices, “Meat”,“Vegetables”, and “Dairy”. When you select one of the choices, the list in the combo box is changed to give a list of choices in the proper category. The popup button has the first choice, “Meat”, selected in IB, so the line setDisplayArray_(array1) in the applicationWillFinishLaunching method ensures that the starting list in the combo box is correct. The bindings were setup like I wrote in the post above.

property parent : class "NSObject"
    property displayArray:missing value -- Array Controller's content array bound to this
    property array1:missing value
    property array2:missing value
    property array3:missing value
    property combo:missing value -- IBOutlet for a combo box
	
	on applicationWillFinishLaunching_(aNotification)
		set array1 to current application's NSArray's arrayWithArray_({"Pork","Beef","Chicken","Veal"})
        set array2 to current application's NSArray's arrayWithArray_({"Carrots","Cabbage","Potatoes","Beans"})
        set array3 to current application's NSArray's arrayWithArray_({"Milk","Cream","Butter","Sour Cream"})
        setDisplayArray_(array1)
	end applicationWillFinishLaunching_
    
    on popupChoice_(sender) -- IBAction for a popup button
        if sender's titleOfSelectedItem() as text is "Meat" then
            setDisplayArray_(array1)
            combo's setStringValue_("")
        else if sender's titleOfSelectedItem() as text is "Vegetables" then
            setDisplayArray_(array2)
            combo's setStringValue_("")
        else if sender's titleOfSelectedItem() as text is "Dairy" then
            setDisplayArray_(array3)
            combo's setStringValue_("")
        end if
    end

Ric

Thanks for the code Ric! That’s awesome! Is it possible to put the code for the arrays in a separate applescript file and load them from there on applicationWillFinishLaunching_(aNotification)?

Thanks,

Charles

Sure, you can put the definition of the arrays in another file, if that’s what you mean. So, I moved the properties and the definitions of the arrays to a new applescript file, got a blue cube in IB and set its class to the new script, and created an outlet in the app delegate to point to that cube. The other script is:

script ArrayFile
    
property parent : class "NSObject"
property array1:missing value
property array2:missing value
property array3:missing value
    
on awakeFromNib()
    set array1 to current application's NSArray's arrayWithArray_({"Pork","Beef","Chicken","Veal"})
    set array2 to current application's NSArray's arrayWithArray_({"Carrots","Cabbage","Potatoes","Beans"})
    set array3 to current application's NSArray's arrayWithArray_({"Milk","Cream","Butter","Sour Cream"})
    log array1
end

end script

And the updated app delegate is:

property parent : class "NSObject"
    property displayArray:missing value -- Array Controller's content array bound to this
    property combo:missing value -- IBOutlet for a combo box
    property otherScript:missing value -- IBOutlet to the ArrayFile script
	
	on applicationWillFinishLaunching_(aNotification)
        setDisplayArray_(otherScript's array1)
	end applicationWillFinishLaunching_
    
    on popupChoice_(sender) -- IBAction for a popup button
        if sender's titleOfSelectedItem() as text is "Meat" then
            setDisplayArray_(otherScript's array1)
            combo's setStringValue_("")
        else if sender's titleOfSelectedItem() as text is "Vegetables" then
            setDisplayArray_(otherScript's array2)
            combo's setStringValue_("")
        else if sender's titleOfSelectedItem() as text is "Dairy" then
            setDisplayArray_(otherScript's array3)
            combo's setStringValue_("")
        end if
    end

Ric

Thank you for taking the time to post the code.

t.

I think I’m not clear on the bindings. The app builds but when I select any item in the popup the combo box’s value gets set to

“<combotestAppDelegate @0x400f7e420: OSAID(4)>”

and I get an error message in Xcode that says

“[combotestAppDelegate popupChoice:]: unable to set argument 2 - [<NSObject 0x40017b600> valueForUndefinedKey:]: this class is not key value coding-compliant for the key array1. (error -10000)”

Could you possibly outline the binding steps in detail?

I’ve deleted all of the bindings and started over on them. Here’s what I have so far:

  1. dragged blue line from popup to app delegate and selected “popupChoice” as the received action.
  2. dragged blue line from app delegate to combo box and selected “combo” as the outlet.

Then this is where I get fuzzy. You say “bind the array controller’s content array to this array, lets call it displayArray” , but I don’t see how to do this. I see an outlet in the app delegate for displayArray that I can bind to the array controller, but I don’t see any way to bind the content outlet of the array controller to displayArray.

Thanks!!
C

Bindings are done differently from connections. You don’t do bindings by dragging, you do them in the binding’s pane of the inspector. Select the array controller, and then the binding’s pane in the inspector (the button with the 3 curvy lines that I suppose represent a knot?). Click the disclosure triangle next to Content Array, then from the popup button select the object (probably app delegate) where you defined the property displayArray, then click the “Bind To” box. At this point Xcode usually puts “self” in the Model Key Path field, change that to displayArray, then (this is important!) tab out of that box and make sure that next to Content Array it has App Delegate.displayArray in parentheses.

Then, you also need to bind the Content property of your popup button. Here, you want to choose Array Controller from the popup button (it may already be set to that) and select the “Bind To” box. You want to have a Controller Key of arrangedObjects and nothing in the Model Key Path field.

Ric

I was close! I made the settings exactly as you listed them and now when I make a selection in the popup, the combo box stays empty. I also get the same message in Xcode’s console when I run the app:

2011-12-06 10:43:22.977 combotest[1024:707] *** -[combotestAppDelegate applicationWillFinishLaunching:]: unable to set argument 2 - [<NSObject 0x40017ba80> valueForUndefinedKey:]: this class is not key value coding-compliant for the key array1. (error -10000)

I thought it might help to take screenshots of the different object’s connection menus…

App Delegate:

Array Controller:

Array File (object that references the other script):

Can you tell from looking what I’m missing? Thanks!!!

BTW, I just tried your code as you originally posted it (without the extra applescript file) and it totally works. I may just do it that way and not take up any more of your time. I really appreciate you taking the time to help out!!

C

I don’t see anything wrong there. What code do you have in the applicationWillFinishLaunching method?

Ric

I had (before trying it without a separate file for the arrays) “setDisplayArray_(otherScript’s array1)”
C

It looks like from your error message that there may be something wrong with your ArrayFile file. If I comment out the property, array1, in my ArrayFile script and run, I get this error message:

2011-12-06 10:14:56.144 MultipleArrays[2998:707] *** -[AppDelegate applicationWillFinishLaunching:]: unable to set argument 2 - [<ArrayFile 0x400e97f60> valueForUndefinedKey:]: this class is not key value coding-compliant for the key array1. (error -10000)

Notice how my error message has <ArrayFile 0x400e97f60> in it whereas yours has <NSObject 0x40017ba80>. I’m not sure why that should be. If you select your ArrayFile in the files pane on the left, what does it show in the inspector for the file name and file type?

Ric

ArrayFile.applescript
Default - AppleScript uncompiled source

Do I need to open and compile it in ScriptEditor?
C

No, I don’t think so – mine says the same thing. I’m at a loss now. Is your code in that file identical to what I posted? I really can’t figure out what’s different.

Ric

I hope so! I just copied and pasted for both files. I’ll double check. It seems to me, since it throws that error while it’s launching that the problem is either in ArrayFile.applescript or with it’s binding. Maybe not?

C

The ArrayFile doesn’t have any bindings (or it shouldn’t any way), it does have connections. Try this. Add the line “log me” to the awakeFromNib method in ArrayFile, and see what that gives you. Does it give you the same thing as you get in the error message, i.e. <NSObject 0x40017ba80> (the number will be different each time you launch, but you should get the same number in the log and error message)?

Ric

I went through and redid all of the connections and bindings again and now there are no errors logged when it launches, but when I make a selection from the popup I get this:

2011-12-06 13:02:44.458 combotest[2188:707] *** -[combotestAppDelegate popupChoice:]: unable to set argument 2 - [<NSObject 0x400a0fde0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key array1. (error -10000)

C

hmmm… This is a real mystery. You can PM me and send me a copy of your project if you want, and I’ll take a look at it.

Ric