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

Buttons are one of the most frequently used elements in an application. In this article, we will add a “Quit” button to the Cocoa Hello World so that the application can quit from the button as well.

This article will continue from the Cocoa Hello World created in the previous article. If you have created it according to the previous article, use it. 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, the button itself is a view. When the button is clicked, the action set to the button is executed. The target is an instance that executes 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 targets.

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 think of setting 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(_:))

Selectors can be obtained for methods of classes written in Swift in the same way. However, the code on the Swift should be as follows.

  • Inherit NSObject class
  • Define method with @objc annotation

For example, the following code.

class TestSwiftObj: NSObject {

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

    }
    
}

Add an quit button

We will create an quit button, and in AppKit we set a target and an action for the button. As for the target, since Cocoa Hello World is a very small app, we will make ViewController as target.

Action Implementation

Since we make ViewController to be a target, we will also add methods to ViewController that will be the action. 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 an action is implemented with 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 that is compatible with Objective-C selectors, so @objc is not needed. (It will internalize the @objc process.)

Add an 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 a little 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 label “Hello World”.
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 it 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 guide lines 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 guide lines are shown as indicating just the center of the view.

If you follow the guide lines, 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 logic. Business logic should be done on the model side and not in the controller.

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

A view controller 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.

It is best to avoid such a situation in terms of code visibility and maintainability. In reality, though, many times I have written such codes. I would like 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.

Serialized Articles

This article is part of a series of articles titled “How to create macOS Apps with AppKit”. For other articles, please open the following links.

How to create macOS apps with AppKit List of Serialized Articles

Let's share this post !

Author of this article

Akira Hayashiのアバター Akira Hayashi Representative, Software Engineer

I am an application developer loves programming. This blog is a tech blog, its articles are learning notes. In my work, I mainly focus on desktop and mobile application development, but I also write technical books and teach seminars. The websites of my work and books are here -> RK Kaihatsu.

TOC