Search code examples
swiftbindingnsarraycontrollernspopupbutton

binding NSPopupbutton to an array of classes


I'm having difficulty binding a NSPopUpButton to an NSArrayController. The array controller manages an array (plants) of the the class Plant, which has a property named commonName which should be listed in the button. I've searched for several days and I'm unable to discover why this isn't working. I'm able to get the button to display the elements of an array of strings but not with the plants array. When the program runs, the button has no elements and doesn't react to clicking.

I've included a screenshot of the attributes and bindings but here's a description:

ArrayController

  1. Attributes: Mode = Class; Class Name = TestDB.Plant (TestDB is the name of the project)
  2. Binding: Bound to View Controller; Model Key Path = plants

Button Bindings

  1. Content: Bound to Array Controller; Controller Key = arrangedObjects
  2. Content Values: Bound to Array Controller; Controller Key = arrangedObjects; Model Key Path = objectValue.commonName

Here is the code from the ViewController:

class ViewController: NSViewController {

@IBInspectable var plants: [Plant] = []
@IBOutlet weak var plantPopUp: NSPopUpButton!

    override func viewDidLoad() {
            super.viewDidLoad()

        //the real list will be pulled from a database, but I'm using
        //this to test binding the button
        plants = [Plant(commonName: "Asparagus", scientificName: "Asparagus officials"), 
          Plant(commonName: "Beet", scientificName: "Beta vulgaris")]

        //to redraw the button?? Doesn't change anything with or without
        plantPopUp.needsLayout.true
    }   
}

This is the code for the class Plant:

@objc class Plant: NSObject {
    @objc dynamic var commonName: String
    @objc dynamic var scientificName: String

    init(commonName: String, scientificName: String) {
        self.commonName = commonName
        self.scientificName = scientificName
    }
}

Here are screenshots of the attributes and bindings of the NSArrayController and the NSPopupButton. Very grateful for any help.

Attributes and Bindings


Solution

  • Two changes:

    1. You have to make plants also KVC compliant

      @IBInspectable @objc dynamic var plants: [Plant] = []
      
    2. Button Bindings - Content Values: Bound to ... Model Key Path = commonName (delete objectValue.)