New to Swift. Issue connecting data source to combobox.

Hi,


I'm new to Swift and have met an issue populating a combobox with a dataset pulled from a PostGreSQL database. I can connect to the database just fine, but I can't figure out how to set the datasource on the dropdown, or otherwise populate the items in the combobox. I am atempting to connect to the database and populate the dropdown in AppDelegate while my UI is in a storyboard. I'm guessing I'm somehow refrencing the combobox incorrectly?


If I try to add items to the dropdown individually, the code runs fine but the combobox doesn't populate. If I attempt to set the datasource to a dictionary filled with the Keys and Values I get "Cannot assign value of type '[String : Int]' to type 'NSComboBoxDataSource?'."


I know in Windows Forms I can set a name and value for each item in my comboboxes. Is this possible here too?


Thanks in advance for your time.


guard status == PGConnection.StatusType.ok else { //guards from failed connections
                print("Connection to database was unsuccessful")
                print("Error: \(status)")
                return
            }
           
            let res = p.exec(statement: sqlDropdown)
           
            print("select statement result status: \(res.status())")
           
            var dropdownItemsDictionary: [String: Int] = [:]
           
            let num = res.numTuples()
            let ComboBox = NSComboBox()
           
            for x in 0..                let org_id: Int = Int(res.getFieldString(tupleIndex: x, fieldIndex: 0)!)!
                let org_name: String = res.getFieldString(tupleIndex: x, fieldIndex: 1)!
                let org_type: String = res.getFieldString(tupleIndex: x, fieldIndex: 2)!
                let curr: String = res.getFieldString(tupleIndex: x, fieldIndex: 3)!
                let mining_addr: String = res.getFieldString(tupleIndex: x, fieldIndex: 4)!
                print("Entity Index = \(org_id) org_name = \(org_name) org_type = \(org_type) currency = \(String(describing: curr)) mining_addr = \(mining_addr)")
               
                dropdownItemsDictionary[org_name] = org_id
               

                //ComboBox.addItem(withObjectValue: org_name)
            }
            ComboBox.dataSource = dropdownItemsDictionary

Accepted Reply

I suppose that's an OSX App ?

Where is the code you show ? In viewDidload ? elsewhere ?


Where do you define the

NSComboBoxDataSource functions ?


Typically you should:


declare the comboBox (probably as an IBOutlet).

@IBOutlet var comboBox : NSComboBox!     // name should start with lower case)

Declare its datasource, either:

- in IB, by control-drag from comboBox to its viewController and select datasource

or

- in viewDidload of the ViewController where the comboBox is declared

     comboBox.datasource = self // NOT A Dictionary ; I would be surprised your code compiled with ComboBox.dataSource = dropdownItemsDictionary


make the viewController conform to protocol

NSComboBoxDataSource

Implement the needed delegate func (see doc)


To populate the comboxBox, use

func addItems(withObjectValues: [Any])

or

     func addItem(withObjectValue: Any)

Replies

I suppose that's an OSX App ?

Where is the code you show ? In viewDidload ? elsewhere ?


Where do you define the

NSComboBoxDataSource functions ?


Typically you should:


declare the comboBox (probably as an IBOutlet).

@IBOutlet var comboBox : NSComboBox!     // name should start with lower case)

Declare its datasource, either:

- in IB, by control-drag from comboBox to its viewController and select datasource

or

- in viewDidload of the ViewController where the comboBox is declared

     comboBox.datasource = self // NOT A Dictionary ; I would be surprised your code compiled with ComboBox.dataSource = dropdownItemsDictionary


make the viewController conform to protocol

NSComboBoxDataSource

Implement the needed delegate func (see doc)


To populate the comboxBox, use

func addItems(withObjectValues: [Any])

or

     func addItem(withObjectValue: Any)

Yes, it's a Macos application. The code is in AppDelegate. Is that the wrong place for it? I'm also a little confused about what setting comboBox.datasource = self accomplishes, it seems like a self evident statement to me so I must not be understanding its purpose. The combobox is in my main.storyboard, where should NSComboBoxDataSource functions be defined and what purpose would they serve? Thanks again for your help!

The code is in AppDelegate. Is that the wrong place for it?

Probably. If the comboBox is inside a view or window controller (logically, should be) which has a specific class associated, the code to set the comboBox should be in this class (in viewDidLoad or windowDidLoad). I will call this class VCWithCombo in the following


I'm also a little confused about what setting comboBox.datasource = self accomplishes, it seems like a self evident statement to me so I must not be understanding its purpose.


A statement like:

comboBox.dataSource = self //it is dataSource, not datasource which would not compile

means :

  • for me, comboBox, the datasource is defined in the class in which we are now (in this case VCWithCombo) ; I will use the func of the NSComboBoxDataSource protocol to get the data I need for my operations. Those data are in an array, or a dictionary defined in VCWithCombo.
  • which means, this is where the functions you need to set me up (as numberOfItems) or get info from me will be defined here: I delegate to the class instance (here VCWithCombo) to provide those func.

func comboBox(NSComboBox, completedString: String) -> String?

Returns the first item from the pop-up list that starts with the text the user has typed.

func comboBox(NSComboBox, indexOfItemWithStringValue: String) -> Int

Returns the index of the combo box item matching the specified string.

func comboBox(NSComboBox, objectValueForItemAt: Int) -> Any?

Returns the object that corresponds to the item at the specified index in the combo box.

func numberOfItems(in: NSComboBox) -> Int

Returns the number of items that the data source manages for the combo box.

To achieve this, VCWithCombo must be declared as conforming to NSComboBoxDataSource protocol (just add NSComboBoxDataSource after the subclass definition, such as :

class VCWithCombo: NSViewController, NSComboBoxDataSource {


The combobox is in my main.storyboard, where should NSComboBoxDataSource functions be defined and what purpose would they serve?

VCWithCombo should:

- define IBOutlet for the comboBox

- set the dataSource for the comboBox: comboBox.dataSource = self : the view or windowController

- implement the required dataSource protocol functions


Hope explanation above answers this question.

When the comboBox needs to get some information (as the number of items to redraw itself), it will ask to its dataSource (VCWithCombo) to provide it.

And the dataSource has access to the dropdownItemsDictionary, allowing to return dropdownItemsDictionary.count.

The Combo has not to care about this, it has delegated to its dataSource.


Don't hesitate to ask if something is not clear.


Could you show the complete code of the class of the VC where the comboBox is ?