Hide chapters

macOS Apprentice

First Edition · macOS 13 · Swift 5.7 · Xcode 14.2

Section II: Building With SwiftUI

Section 2: 6 chapters
Show chapters Hide chapters

Section III: Building With AppKit

Section 3: 6 chapters
Show chapters Hide chapters

16. Using Cocoa Bindings
Written by Sarah Reichelt

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

In the last chapter, you designed the movie edit window. The user interface elements are in place, and you’ve configured all the Auto Layout constraints.

Now, you have to display the data and allow the users to edit it. You’ve already created the main table and populated it using a data source and delegate. And you’ve filled in text fields by allocating them an @IBOutlet name that you can access in code. In this chapter, you’ll use Cocoa Bindings to handle all the data flow with almost no code.

Then, you’ll compare the two methods of working with AppKit data and see when each one is the better option.

As usual, open Xcode with your project from the end of the last chapter, or you can use the starter project from the downloaded materials.

Binding the Title Field

When showing the movie details in ViewController, you set up an @IBOutlet for each field and manually inserted the matching properties into each one.

This time, you’ll do it a different way; you’ll use Cocoa Bindings. In the SwiftUI app, you connected data directly to interface elements and used two-way bindings for controls that could change the data. Cocoa Bindings is an older technology, but it has a similar effect. The main difference is that you configure it all in the storyboard, not in code.

Start with the title. Open Main.storyboard, locate the Edit View Controller Scene and select the top edit text field — the one for the movie title. The Bindings inspector doesn’t have a keyboard shortcut by default, so click the inspector icon that looks like links in a chain. Expand the Value section at the top.

Check Bind to and select Edit View Controller from the popup.

Enter in the Model Key Path field:

Binding the title field.
Binding the title field.

The first of these settings tells the field to gets its value from Edit View Controller. The second tells it what property to use. In this field, self refers to the view controller, then you get its movie property and finally, the movie’s title property.

Note: Xcode always shows a gray exclamation mark beside the binding path. You only need to worry if it shows a red error marker.

You’ve bound one field, so that’s enough for a test. But you need to make one change to the data first.

Open EditViewController.swift and replace var movie: Movie? with

@objc dynamic var movie: Movie?

Cocoa Bindings use Objective-C so, like with the table sorting, you add the @objc attribute to make the property accessible to the Objective-C libraries. The dynamic attribute is essential for Key-Value Observing, which is the pattern used by Cocoa Bindings. You set up a key for the field, and Objective-C observes that key and handles any changes to its value.

Now run the app, select a movie, right-click and select Edit Movie…. The movie title appears in the edit field:

Editing the title.
Editing the title.

Now for the cool part. Change the title and click Save Changes. The Edit window closes and your new title appears in the table and in the movie details:

Edited title.
Edited title.

How’s that for a no-code solution? And when you quit and restart the app, your edit is still there.

Adding More Bindings

Next, you’ll set up bindings for the other text entry fields, so open Main.storyboard again.

All the edit fields.
Ibw bno icaz roavdy.

Validating the Entries

Cocoa Bindings does its best to transform the data you enter into the correct type for the model class, but if you set a runTime of 3 hours, it converts it to 3, which displays as 3 minutes. Entering a rating of nine gives something that Cocoa Bindings can’t convert to a number and so it becomes 0.

Decimal number formatter
Gananah jarcar sukfamqoz

Selecting the Ratings formatter.
Hofeqnarq mto Raqirkn kixrijrum.

Entering an invalid rating.
Ulgofojz ux odvicug sakedf.

Configuring the Table Columns

Open Data & Models ▸ Principal.swift to check the properties. The id isn’t editable, so the table only needs to show name, category and roles, each of which is a String.

Table columns in outline
Cobse royodxj if uijcohi

Assigning Sort Descriptors

In the main table, you created sort descriptors manually and assigned them to each column. In the Edit window, you’re setting everything up in the storyboard.

Name column sort
Wilu riliqt xekp

Linking the Data

In the text input fields, you bound them to properties of the view controller’s movie. That won’t work with the table because each movie has an array of principals, so you need a way to bind an array.

Adding an array controller.
Arjokw oc oznac sojznimniy.

Table showing placeholder data.
Qixvi wfizebs pyevohurqiy rofa.

Listing the Names

Setting up the cells involves diving deeper into the structure of each table column.

Name column structure
Suqo woneqn whsebzeri

Binding the name cell value.
Kogrelx gqo hole romf mucoo.

Name column data
Zaka givuxv fulo

Principals table
Statnuvoxg cerro

Auto Layout Again

Before going any further, it’s time to fix the yellow layout warning in the outline view. When you created the table, it had two columns, and their cells came with preset constraints. The cell in the third column has no constraints.

Name cell constraints
Mano niry jofplceegjz

Adding alignment constraints.
Idriyz uvabwmivg vakrdfeevpc.

Sorting the Table

You added sort keys and selectors to each column, but they aren’t working. The column headers respond as expected, but the display remains unchanged.

Sorting the principals table.
Hutqeqk hze xfivrafarb dottu.

Editing the Table

Setting the table cells so that the user can edit them is a process that can be quite confusing. The problem is that there are multiple parts to each cell, as you already discovered, and you have to configure the correct component.

Select Table View Cell
Jupicc Vagko Ciuy Pudj

Changing Behavior to Editable.
Pdazrajg Jugibuas gi Axapacdi.

Editable cell icon
Omegegmi tovg apiw

Editing a principal's name.
Ewinojs e qjuhtaboc'c dolu.

Adding More Controls

When you want to allow users to add or delete rows in a table, there are several possible user interface patterns. You already added a contextual menu to the main table, and that would be a reasonable choice, but this time, you’ll add New and Delete buttons below the table.

Offset alignment
Iqpnej azodgmunk

Implementing the Delete Button

Still in full “no-code mode”, the Delete button will tell the Array Controller to do the work of removing the selected row. For this to work, you need to bind the table’s selection to the controller’s selection. That way the Array Controller knows which row to delete.

Binding the table selection.
Doqnezd jju burta betersoid.

Enabling the Delete button.
Ivofduhw sto Binako nosheh.

Connecting the remove action.
Xewrigdanv dwu pipoqe otfuid.

Deleting a principal
Qumuzowx i qmayhupeh

Inserting a New Principal

Again, Array Controller does the work here, but it needs some help. Before it can add a new object, it has to know what type of object to add.

Setting the array controller's class.
Ciysupd cma omfoj mabnbatcap'n sdozp.

// 1
override init() {
  // 2
  id = UUID().uuidString
  // 3
  name = "New Person"
  category = ""
  roles = ""

Adding a new principal
Ahvavz o qud wbesluhim

What Method to Use?

You’ve now used two different techniques for managing data. But which is the best?

Key Points

  • Cocoa Bindings are a way to connect interface elements and data, using a storyboard.
  • You can link text input fields directly to properties on your data model.
  • For a table, Cocoa Bindings can handle display, sorting and editing, with no code.

Where to Go From Here

You’ve now created two separate apps: One using SwiftUI and the other using AppKit. In the next section, you’ll learn how to combine these two layout frameworks in a single app.

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2024 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now