Chapters

Hide chapters

macOS by Tutorials

First Edition · macOS 12 · Swift 5.5 · Xcode 13

Section I: Your First App: On This Day

Section 1: 6 chapters
Show chapters Hide chapters

8. Working with Timers, Alerts & Notifications
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 previous chapter, you set up a menu bar app using AppKit. You designed a custom view to display the app’s tasks in the menu, and you monitored the menu so as to add and remove them as needed.

So far, the app isn’t doing anything active with the data, but that’s about to change!

Now, you’ll wire up menu items from the storyboard to your code and run a timer to track the progress of tasks and breaks. Then, you’ll look into using system alerts and local notifications to tell the user what’s going on.

Linking Outlets and Actions

You’ve created some static menu items to allow control of the app, but they don’t do anything yet. The first task is to link them to code, so you can access them and make them work.

In Xcode, open your project from the last chapter or open the starter project in the download materials for this chapter.

Open Main.storyboard and fully expand Application Scene in the Document Outline. Option-click AppDelegate.swift in the Project navigator to open it in a second editor.

Right now, you have a menu item titled Start Next Task but, if a task is running, it should have a different title. This means that you need to connect it to AppDelegate, so you can access the menu item programmatically. And since you want this menu item to do something, you also need to connect an AppDelegate method to it.

When you Control-drag from a storyboard into a .swift file, Xcode offers to create an Outlet or an Action. An outlet gives you a name you can use to refer to an object on the storyboard. An action works the other way around, giving the object on the storyboard a method it can call. Conveniently, if you Control-drag to near the top of your class, Xcode assumes you want to make an outlet, and if you Control-drag further down, it assumes an action.

You aren’t going to use all the connections yet, but since you’re here, it makes sense to set them all up.

Connecting the Outlets

Control-drag from Start Next Task to underneath where you declared menuManager. Don’t let go until you see the Insert Action or Outlet tooltip. You may have to move the mouse pointer down a line to get there:

Jujfwal-qxap
Yotyyut-jcuz

Kihzikrifc it iawrop
Qocvogbokf ot aizwiw

Czu aapkeq ej zuki
Xfu iejzuv az yiho

Seyduzvomh lri coymednein
Hukxajkovc lto wesveldour

Wiring Up the Actions

Control-drag from Start Next Task into this blank space and connect an action called startStopTask:

Vukqihkegm as etzouz
Jogqaflach ev omfoul

Lbi utvooch il piyi
Pfe omkeocr ef xana

Managing the Tasks

The standard Apple app architecture is MVC, which stands for Model View Controller. The model is the data, the view is how you display it and the controller sits in the middle. Unfortunately, it’s horribly easy to pile far too much responsibility onto the controller. That leads to a humorous new definition for the acronym: Massive View Controller.

Timers

It’s finally time to talk about timers. After all, what’s the point of a timer app that can’t time anything? :]

Leket cantaxsemd celup
Pipoy quzfeyyiql xugof

Tracking the Timer State

When running this app, the timer can be in one of four states:

Starting and Stopping Tasks

Still in TaskManager.swift, add these methods for starting and stopping tasks:

Sesx ok pjentubn
Laqh ir nwoqpacm

Updating the Menu Title

There are three parts of the menu that you need to update: the menu title, the startStopMenuItem title and the tasks themselves.

Duwi wixba muexwafk vulk
Pega podmo pieyfotw buvp

Updating the Tasks

You’ve done two of the three updates needed, but the menu item showing the active task is only updating when the menu opens or when you move the mouse pointer over it.

Jeki eyegb ifzujojy
Xojo orucr olsiduxy

Checking the Timer

This is another job for TaskManager, so open TaskManager.swift and add these methods:

Ox a zjovp cdoob
Ej a cnoqx jduin

Ew e zoql rfoar
Oc e rerq tqaoh

Creating Alerts

You’ll use NSAlert to communicate with your users. This is a standard dialog box where you supply a title, a message and, optionally, a list of button titles. In UIKit programming, you’d use UIAlertController for this.

Showing Alerts

The alert code is all there now, but you still need to set up an instance of Alerter and add the calls to use it.

Dezs koxpnebo omudb
Wicp cafnkoje ekask

Preub oxun uhocb
Qtuaq ehib egifb

Using Local Notifications

You may be wondering if local notifications would be a better choice for communicating with the user.

Erjixk sic gasuyakapauy cokzekteufg
Exxugf ket cukedubeteek lutjiqsoudx

Zary sepqjaqo mosofehipuuf
Xezh hoynvuxa weyefedukeuv

Lnuah valrdazi horevopitaat
Dqeob kamdjene pogaputoqoec

Picking a User interaction

Which do you think is better: alerts or notifications?

Key Points

  • With AppKit apps, like UIKit apps, you have to make connections between the storyboard and the code.
  • There are two main ways to create a timer. This app uses a Combine TimerPublisher.
  • Using an enumeration is a great way of tracking changing states in your app.
  • Enumeration cases can have associated values, which make them even more powerful.
  • You can update the menu title and the menu items regularly, even if the menu is open.
  • With a custom NSView, you only have to tell it that its display needs updating to trigger a complete redraw.
  • System alerts provide a standard way of communicating with the user.
  • Local notifications are a way of contacting the user less intrusively.

Where to Go From Here?

At the start of this chapter, your app was displaying the task data in your status bar menu, but nothing else was happening.

© 2026 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