macOS Controls Tutorial: Part 1/2

Learn how to use common macOS UI controls like NSTextField, NSComboBox, NSButton, and more in this two-part series — updated for Xcode 11.3 and Swift 5! By Roberto Machorro.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 5 of this article. Click here to view the first page.

Method 2 – Using A Data Source

When using a data source the combo box will query the data source for the items it needs to display as well, as any necessary metadata, such as the number of items in the list. To obtain this information, you’ll need to implement the NSComboBoxDataSource protocol in one of your classes, normally the View Controller hosting the control. From there, it’s a two-step process to configure the combo box to use the data source.

First, set the control’s usesDataSource property to true. Then set the control’s dataSource property, passing an instance of the class implementing the protocol; when the class implementing the data source is the hosting View Controller a good place for this setup is viewDidLoad(), and then you set the dataSource property to self as shown below:

class ViewController: NSViewController, NSComboBoxDataSource {
.....
  override func viewDidLoad() {
    super.viewDidLoad()
    myComboBox.usesDataSource = true
    myComboBox.dataSource = self
  }
.....
}

Note: The order of the instructions in the code above is important. An attempt to set the dataSource property when useDataSource is false (which is the default) will fail and your data source will not be used.

Note: The order of the instructions in the code above is important. An attempt to set the dataSource property when useDataSource is false (which is the default) will fail and your data source will not be used.

In order to conform to the protocol, you’ll need to implement the following two methods from the data source protocol:

// Returns the number of items that the data source manages for the combo box
func numberOfItems(in comboBox: NSComboBox) -> Int {
  // anArray is an Array variable containing the objects
  return anArray.count
}
    
// Returns the object that corresponds to the item at the specified index in the combo box
func comboBox(_ comboBox: NSComboBox, objectValueForItemAt index: Int) -> Any? {
  return anArray[index]
}

Finally, whenever your data source changes, to update the control, just call reloadData() on the combo box.

Which Method To Use?

If your list of items is relatively small and you don’t expect it to change that often, adding items once to the internal list is probably the best choice. But if your list of items is large or dynamic, it can often be more efficient to handle it yourself using a data source. For this tutorial you’ll be using method 1.

Now that you’ve covered the fundamentals of the combo box, move on to implement one in your app! :]

The Singles Bar – A Singular Noun

In this section you’ll add a combo box to enter a singular noun. You can either choose from the list or enter your own.

First, add a label that describes what the control is for.

Open Main.storyboard. Locate the Label control in the the Object Library palette, and drag it onto the content view. Change its alignment to Right and its title to Singular Noun:.

Note: Alternatively as a shortcut, hold down the Option key and drag an existing label to duplicate it. This is handy so you can keep the same size and properties of an existing label.

Note: Alternatively as a shortcut, hold down the Option key and drag an existing label to duplicate it. This is handy so you can keep the same size and properties of an existing label.

Locate the Combo Box control and drag it onto the content view, placing it to the right of the label.

Now you need to add an NSComboBox outlet to the view controller. Use the same technique you used for the text field: select the Assistant Editor (making sure ViewController.swift is selected) and Ctrl-Drag the combo box to the ViewController class just below the NSTextField:

In the popup window that appears, name the outlet singularNounCombo.

Now the NSComboBox property is connected to the combo box control. Next you are going to add some data to populate the list.

Open ViewController.swift and add this code under the outlets:

fileprivate let singularNouns = ["dog", "muppet", "ninja", "pirate", "dev" ]

Now, add the following code at the end of viewDidLoad():

// Setup the combo box with singular nouns
singularNounCombo.removeAllItems()
singularNounCombo.addItems(withObjectValues: singularNouns)
singularNounCombo.selectItem(at: singularNouns.count-1)

The first line removes any items added by default. Next, it adds the names from singularNouns to the combo box using addItems(). Then, it selects the last item of the list.

Build and run the application to see your combo box in action!

Great – it looks as though everything is working just right. If you click on the combo box, you can then view and select any of the other items.

Now, what if you wanted to present a list of choices, but not allow you to enter your own? Read on, there’s a control for that as well!

Pop Goes the Weasel – NSPopupButton

The pop up button allows the user to choose from an array of options, but without giving the user the option of entering their own value in the control. The macOS control responsible for this is NSPopupButton.

Pop up buttons are incredibly common in macOS, and you can find them in almost every application – including the one that you’re using right now: Xcode! :] You’re using the pop up button to set many of the properties on the macOS controls you’re using in this tutorial, as in the screenshot below:

Filling the Spaces – Adding Items To Pop Up Buttons

As you might expect, adding items to NSPopUpButton is similar to adding items to NSComboBox – except that NSPopUpButton doesn’t support using a data source for the content of the control. NSPopUpButton maintains an internal list of items and exposes several methods to manipulate it:

// Add an item to the list
myPopUpbutton.addItem(withTitle: "Pop up buttons rock")

// Add an array of items to the list
myPopUpbutton.addItems(withTitles: ["Item 1", "Item 2", "Item 3"])

// Remove all items from the list
myPopUpbutton.removeAllItems()

// Get the index of the currently selected item
let selectedIndex = myPopUpbutton.indexOfSelectedItem

// Select an item at a specific index
myPopUpbutton.selectItem(at: 1)

Pretty straightforward, isn’t it? That’s the beauty of macOS controls – there are a lot of similarities between them in terms of the methods used to manipulate the controls.

Time to implement a pop up button in your app! :]

Contributors

Gabriel Miro

Tech Editor

Chris Belanger

Editor

Michael Briscoe

Final Pass Editor and Team Lead

Over 300 content creators. Join our team.