Cocoa Bindings on macOS

Cocoa bindings make glue code a thing of the past. Discover how you can simplify your controller code in this Cocoa Bindings on macOS Tutorial! By Andy Pereira.

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

Your First Bindings

It’s time to get to the meat of this tutorial!

allthethings1

The first step is to bind the array controller to the table view.

Open up Main.storyboard and select the table view titled Search Results Table View (Bind). Open the Bindings Inspector: it’s the second-to-last-icon in the right pane, just before the View Effects Inspector.

Expand the Content option under the Table Contents heading. Check the box next to ‘Bind to ‘ and make sure Search Results Controller is displayed in the dropdown box. Finally, make sure the Controller Key is set to arrangedObjects, like so:

TableViewBinding

Build and run, and search for something you know will return a large number of results. You’ll see at most five results, unless you changed the number in the dropdown. Thanks to the bindings, the array controller automatically represents its content in the table view. However, they all say “Table View Cell”.

arrayboundnotitlesintable

You’re getting a bunch of duplicate hits because the text fields in the cells have no idea which properties on the data model they should read.

Binding Text Fields to Their Properties

Open up Main.storyboard and go to the View Controller Scene. Expand the objects in the table view until you find the text field named Title TextField (Bind). Select this object and open the Bindings Inspector.

Expand the Value option and bind to the Table Cell View object. Ensure the Model Key Path is objectValue.trackName.

objectValue is a property on the table cell view that gets set by the NSTableView on each cell view object from its binding to the table.

objectValue is, in this case, equal to the Result model object for that row.

trackName

Repeat the above process for Publisher TextField (Bind) by binding the value of this element to objectValue.artistName.

Build and run, and search again. This time, the title and publisher show up:

title and publisher

Adding in Rank

How about that missing rank column? Rank isn’t set on the data model object you get from iTunes. However, the order of the results from iTunes does tell you the order in which they display on a device when searching iTunes.

With a little more work you can set the rank value.

Add the following code in ViewController under the //Deal with rank here later comment:

.enumerated()
.map({ index, element -> Result in
  element.rank = index + 1
  return element
})

This code calls enumerated() in order to get the index and the object at the index. Then it calls map(:_) to set the rank value for each object and return an array with that result.

Now, go back to Main.storyboard, select Rank TextField (Bind) and open the Bindings Inspector. In the Value section, bind to the Table Cell View. Make sure Controller Key is empty, and set Model Key Path to objectValue.rank.

Build and run, and the app shows the rank in the first column of the table view:

ranktitlepublisher

Now you need to bind the Result object selected by the user to the rest of the UI.

Binding a Table View’s Selection

Binding to a selection in a table involves two steps:

  1. You first bind the NSArrayController to the table selection.
  2. Then you can bind the properties of the selection object in the NSArrayController to the individual labels and other properties.

Open Main.storyboard. Select the Search Results Table View (Bind) and open the Bindings Inspector.

Expand the Selection Indexes option in the Table Content section. Check Bind to the Search Results Controller object.

Enter selectionIndexes into the Controller Key box. The table has a selectionIndexes property that contains a set of indexes that the user has selected in the table.

In this case, I’ve set the table view to only allow a single selection. You could work with more than one selection if your app requires it, similar to how Finder lets you select multiple files.

selectionIndexes

The NSArrayController object has a selection property that returns an array of objects. When you bind the selectionIndexes property from the table view to the array controller, the selection property will be populated with the objects in the array controller that correspond to the indexes selected in the table.

The next step is to bind the labels and other UI elements to the selected object.

Find and select the App Name Label (Bind). Bind its value to the Search Results Controller. Controller Key should be selection, and Model Key Path should be trackName.

mainTrackName

Build and run, select any app in the table view and its title will appear in the text field:

Main Title

You’ve seen how easy it can be to get data from your model into your UI. But what if the data needs to be formatted in some way, such as a currency or as a date?

Luckily, there’s a built-in set of objects that make it easy to change the way a specific piece of data is displayed in a label.

Formatting Bound Data

Find the label titled Price Label (Bind). Bind it to the Search Results Controller object, and ensure Controller Key is selection.

Set Model Key Path to price. Next, find a Number Formatter in the Object Library. Drag it to the NSTextFieldCell named Label, just under the Price text field.

Finally, select the Number Formatter, open the Attributes Inspector and change the Style to Currency.

When you’re done, your storyboard and inspector should look like the following:

currencyFormatter

Build and run, select any app from the list and the currencies should all display correctly:

priceformatted

Note: Number formatters are very powerful. In addition to currencies, you can also control how many digits follow a decimal point, percentages, or have the number spelled out in words.

There are formatter objects for dates, byte counts and several other less-common situations. If none of those suit your needs, you can even create your own custom formatters.

Formatting as Bytes

You’ll be using a Byte Count Formatter next to show the file size.

Find and select File Size Label (Bind), open the Bindings Inspector and bind it to the Search Results Controller. Set Controller Key to selection and Model Key Path to fileSizeInBytes.

Then find a Byte Count Formatter in the Object Library and attach it to the NSTextFieldCell. There’s no need to configure anything here; the default settings on a byte formatter will work just fine.

You should see your byte count formatter in the document outline like so:

byte count formatter

Build and run, select an app in the list, and you’ll see file size using the proper units, such as KB, MB, and GB:

byte count final

You’re quite used to binding things by now, so here’s a short list of the remaining keys you need to bind:

  • Bind the Artist Label (Bind) to artistName.
  • Bind the Publication Date (Bind) to releaseDate.
  • Add a Date Formatter; the default settings are fine.
  • Bind the All Ratings Count (Bind) to userRatingCount.
  • Bind the All Ratings (Bind) to averageUserRating.
  • Bind the Genre Label (Bind) to primaryGenre.

All these labels should be bound to the Search Results Controller and the selection controller key.

For more precision in your UI, you can also bind the Description Text View (Bind), the Attributed String binding, to the itemDescription Model Key Path. Make sure you bind the NSTextView, which is several levels down in the hierarchy, not the NSScrollView which is at the top.

selecttextView

Build and run, and you’ll see most of the UI populate:

mostly populated