How to create buttons in AppKit (about targets and actions) | How to create macOS Apps

Buttons are among the most frequently used elements in applications. In this article, we will add a “Quit” button to the Cocoa Hello World so that the application can also quit from the button.

This article will continue from the Cocoa Hello World created in the previous article. If you’ve already created it following the previous article, you can use that. If not, please download the sample code from the end of the previous article.

TOC

Action and Target

When creating buttons in AppKit, “Action” and “Target” are used. In AppKit, a button is actually a view. When the button is clicked, the action set to the button will be executed. The target refers to the instance that will execute the action.

Operation when button is clicked
Operation when button is clicked

About the target entity

The entity of the target that executes the action is an instance of a subclass that inherits from the NSResponder class. AppKit also has many classes that inherit from the NSResponder class. For example, the NSWindow class and NSWindowController class, which implement windows, also inherit from the NSResponder class and can be the target.

About the action entity

The entity of an action is a selector. Selectors are the internal representation of Objective-C methods. When developing an application, you can set a selector as setting a method.

For example, assume that the following method in Objective-C is available.

@implementation TestObj

- (void)doSomething:(id)sender
{
}

@end

The selector for this doSomething method is written as follows.

SEL theSelector = @selector(doSomething:);

In Swift, the selector for the method of this Objective-C class is written as follows.

let theSelector = #selector(TestObj.doSomething(_:))

The selector for methods of classes written in Swift can be obtained similarly. However, the code on the Swift should be as follows.

  • Inherit NSObject class
  • Define method with @objc annotation

For example, the following code implements the above.

class TestSwiftObj: NSObject {

    @objc func doSomething(_ sender: AnyObject?) {

    }
    
}

Add a quit button

We will create a quit button, and in AppKit, we will set a target and an action for the button. Since Cocoa Hello World is a minimal app, we’ll designate ViewController as our target.

Action Implementation

Since we’re designating ViewController as the target, we’ll add the methods to ViewController that will serve as actions. For example, add the following code to ViewController.swift.

import Cocoa

class ViewController: NSViewController {
    // 省略
    
    @IBAction func terminateApp(_ sender: Any?) {
        NSApplication.shared.terminate(sender)
    }
}

Define as an action

The method to be made into action is implemented with a code of the following form.

@IBAction func methodName(_ sender: Any?) {
}

Use @IBAction instead of @objc. @IBAction is an attribute required to make Xcode recognize a method as an action. @IBAction also exports methods in a way compatible with Objective-C selectors, so @objc is unnecessary. (It will internalize the @objc process.)

Add a quit button to the view

Add a quit button to the view by doing the following.

STEP
Open the “Main.storyboard”.
STEP
Select the “View Controller Scene”.
STEP
Click the “+” button (“Library” button) on the toolbar.
Click the "Library" button
Click the “Library” button
STEP
Drag and drop the “Push Button” from the Library window below “Hello World” in the view. A guide will appear in just the right place.
Add buttons to the view by dragging and dropping
Add buttons to the view by dragging and dropping
STEP
Double-click on the button you have placed. When the title becomes editable, type “Quit” and press the “Return” key.
Set the button title
Set the button title

Auto Layout Settings

Next, set the auto-layout. The label “Hello World” is to appear in the center. The “Quit” button is set to appear below it. The following is how to do it.

STEP
If the “Quit” button is not selected, select it.
STEP
Click the “Add New Constraints” button.
Click the "Add New Constraints" button.
Click the “Add New Constraints” button.
STEP
Check “Width” and “Height” and click “Add 2 Constraints”. This will fix the width and height.
After checking "Width" and "Height", add Constraints
After checking “Width” and “Height”, add Constraints
STEP
Click “Add New Constraints” again, click the pop-up icon (downward pointing triangle) in the upper margin column, and select “Hello World (current distance = 8)”. This will set the Y coordinate at 8px below the “Hello World” label.
Set the top margin
Set the top margin
STEP
Click the “Align” button.
Click the "Align" button
Click the “Align” button
STEP
Check “Horizontally in Container” and click “Add 1 Constraint”.
Centered horizontally
Centered horizontally

Set the action on the button

Finally, set the terminateApp method to the “Quit” button’s action. Operate as follows.

STEP
Right-click and drag the “Quit” button, or hold down the “Control” key while dragging. A blue line will appear and drop onto the “View Controller” in the “View Controller Scene.
Make a connection from the button to the ViewController
Make a connection from the button to the ViewController
STEP
Select “terminateApp:”. This will set the “terminateApp” method to the button action.
Select the action
Select the action

About Guide Lines

The horizontal guidelines are shown when adding a button. They are shown at the margins that should be left empty according to the Human Interface Guidelines. Also, the vertical guidelines are shown as indicating just the center of the view.

If you follow the guidelines, you can lay out the layout to a certain degree of goodness.

The Human Interface Guidelines are available on the developer site.

Fat View Controller and Fat Window Controller

Here we implemented the quit function, which is business logic, in ViewController. In doing so, we emphasized the “small scale” nature of AppKit, which was originally designed with MVC.

View controllers and window controllers are controllers. The controller is to communicate input to the model. The process of exiting is logical. Business logic should be done on the model side and not in the controller.

However, Cocoa Hello World is very small. Therefore, it was considered rather over-speculative to strictly divide the code in an application as small as this. Consequently, we implemented it directly in ViewController.

A view or window controller that has grown so large because everything has been implemented in a controller is called a “Fat View Controller” or “Fat Window Controller.

For code visibility and maintainability, it’s best to avoid these situations. In reality, though, many times, I have written such codes. I want to improve these codes someday.

Running Test

Build and run the application. Resize the displayed window and make sure the “Quit” button is not positioned incorrectly.

Next, click the “Quit” button and see if the application exits.

Test of Hello Word
Test of Hello Word

Download the sample code

The sample code created for this article can be downloaded here.

Authored Books

Let's share this post !

Author of this article

Akira Hayashi (林 晃)のアバター Akira Hayashi (林 晃) Representative(代表), Software Engineer(ソフトウェアエンジニア)

アールケー開発代表。Appleプラットフォーム向けの開発を専門としているソフトウェアエンジニア。ソフトウェアの受託開発、技術書執筆、技術指導・セミナー講師。note, Medium, LinkedIn
-
Representative of RK Kaihatsu. Software Engineer Specializing in Development for the Apple Platform. Specializing in contract software development, technical writing, and serving as a tech workshop lecturer. note, Medium, LinkedIn

TOC