3 Replies
      Latest reply on Jan 14, 2020 8:45 AM by Claude31
      JacobMcD Level 1 Level 1 (0 points)

        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
        • Re: New to Swift. Issue connecting data source to combobox.
          Claude31 Level 8 Level 8 (7,895 points)

          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)

            • Re: New to Swift. Issue connecting data source to combobox.
              JacobMcD Level 1 Level 1 (0 points)

              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!

                • Re: New to Swift. Issue connecting data source to combobox.
                  Claude31 Level 8 Level 8 (7,895 points)

                  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 ?