Let’s Code

Okay so now we need to setup our clock app, almost all our code will be placed in the AppDelegate class.

Default AppDelegate

We can easily delete the applicationWillTerminate method, right now we don’t need it.

Then we can create our NSStatusItem this will be our item in the status bar, more specifically will be the container for our button.

To create our status bar item just write the following:

We have assigned a placeholder text for the moment, now it’s time to schedule a timer that updates our title with the current time every second.

To do that we declare another class variable named timer with optional type Timer? and make it nil by default.

Then in the applicationDidFinishLaunching under our title assignment, we can create our Timer like the following

I’ve also created an objective-c function that is called every time the Timer gets fired (every second).

Below some utility functions to make everything more readable and clean, one is for the Date class and the other one is for Int .

Date Extension

Int Extension

Ok now you can run your app and if you’ve done everything right, you should have your clock in the status bar.

Congratulations! 🎉 You’ve built your first MacOS Application! But wait! We have a bug! Maybe you haven’t noticed yet but if the statusBarItem is highlighted it will not update until we move our focus out of it.

To fix that we need to edit our Timer and add a row to start it like the following:

AppDelegate

Awesome! You’ve fixed your first bug in the app! Now let’s make it a little bit more interesting 💪

✏️ Add a Menu

Okay now it’s time to make our application more user-friendly, let’s add some features and preferences.

First of all let’s write some code to handle our Preferences, to do that I usually create a struct that handles UserDefaults for small settings like booleans numbers, strings, enums, etc.

This is a really useful helper!

Now we can move with the menu stuff, declare a new menu variable in the AppDelegate and create a menu with NSMenu() then add some items, like:

Flashing time separators

Show/Hide Seconds

Show/Hide Dock Icon (we’ll se how later)

Quit the application (quite useful)

Before we go through the code I want to share with you other 2 little extensions that will help to archive good code readability and functionality

So.. now I’ve refactored a bit the AppDelegate to make it more clear and concise. That’s how it looks with the menu implementation:

This is how the application is looking right now:

By the way, now it’s missing some implementations.

The useFlashingDots and showDockIcon items are useless at the moment. Instead of these functions the showSeconds setting it’s handled in the updateStatusText function.

Inside each NSMenuItem action we update the item it self with the new preferences, since these are checkboxes we update the state, the stateValue in Bool+Extension.swift its a statement that returns .on or .off respectively when a Boolean is true or false . This saves us from writing Preferences.showDockIcon ? .on : off instead of Preferences.showDockIcon.stateValue .

️️⚙️ ️Preferences: The Dock Icon

Okay, here we are, we have a status bar application but we also have a dock icon, and as a status bar application, we don’t want the dock icon to be visible.

Look at the top right corner of your monitor, do you see them?

Imagine if every app in your status bar would have an icon in your dock… That’s not great user experience.

We can handle the Dock Icon via NSApplication.ActivationPolicy . To do that I wrote a little helper, a struct with 2 methods to set/read the A ctivationPolicy.

DockIcon Helper

We can now edit the toggleDockIcon method to handle this preference, let’s see how implement this helper.

At line 7 we’ve implemented the DockIcon helper

Now copy and paste the method you’ve just written (line 7 of the gist above) at the end of the applicationWillFinishLaunching method.

At line 12 we’ve implemented the DockIcon helper

Hiding/Showing the Dock icon

⚙️ Preferences: Flashing Separators

Now it’s the time of “flashing separators”, how can we make a better clock if the standard one has more functionalities? So let’s implement this simple feature that even Apple’s default clock has.

How? Easier than you think, we need a variable that handles the status of the separators (visible/hidden, or maybe better 0/1, or we can even recycle NSControl.StateValue ) and if it’s 0 do a string replacement in with “:” -> “ “ in our title (remember?).

Method 1

A better way to do that is checking whenever the seconds are even (or odd) and use this instead of the variable (this is ok only if you want to flash dots 1 time per second)

Method 2

Below how it should look like with flashing separators:

The final result

⏰ Reminders…

Wait! We’re missing the core experience of the whole application! Right now why should someone download an alternative clock with no extra features?

So let’s add the reminders feature, it’s pretty simple, and you’ll learn how to create and present a window.

We can start creating a new struct type and call it Reminder

Then create a new variable of type [Reminder] and add empty array as default value.

var reminders: [Reminder] = []

Now we can write some logic stuff:

Add a MenuItem to the StatusMenu

Add a submenu with all the reminders

Add a MenuItem that opens a new window to schedule a new Reminder.

Delegate reminder and the view controller in the AppDelegate

Creating the NSMenuItem and its submenu

As we have already done before for the other elements, let’s create a new NSMenuItem and this one like the statusBarItem will have a menu property, this will be populated with all the reminders inside our reminders variable declared before.

How can I add a new Reminder?

Now we need to create an interface to add reminders, to do that open your Main.storyboard and create a view controller with an NSTextField for the title, NSTextView for the description and NSDatePicker for the date.

You can do this also from code, programmatically, but since this article is becoming really long I’ll show you the fastest way to archive a basic window with controls.

My interface

Ok now let’s create a new file, this will be our view controller, in case you haven’t delete it yet, you should have a file named ViewController, you can edit this one instead of create a new file. Rename it to NewReminderVC and rename also the class inside, you should have something like this one below:

To save time I’ve just added a new Delegate Protocol on top of the file, this will be used to handle the submit event.

Okay, you’re all set, go in your storyboard, select the view controller you’ve just created and assign this new class to it:

Identity Inspector

Make sure to add a Storyboard ID, for practicality I name it just like the view controller class.

We’ll use the Storyboard ID to identify our view later in the code.

Now with the view controller selected, click on the Assistant Editor button on the top right corner of Xcode.

This will split your screen in 2 editors.