Learning to make native Mac apps was difficult for me. With a little searching you can find Cocoa tutorials online, but they invariably only teach the what – things like “this is how you make a button”, or “this is how you make a list” – rather than the why. Maybe this says more about me than anything, but it took me around a year of on-and-off experimentation to feel like I finally had a handle on using Cocoa and could understand how building whole applications is even feasible.
Also, I found that nearly all tutorials relied on Xcode and Interface Builder, which just didn’t gel with me. I much prefer seeing all my work laid out in front of me in the form of code I can read and edit and comprehend, rather than an obscure XML file format generated by a GUI tool. This is why we’ll do everything from scratch – no “New Project” templates or magic IDE interfaces required.
With this tutorial series I want to write the guide I wish I had a year ago. My aim isn’t to teach you everything there is to know – rather, I’d like to help you see how all the pieces fit together so you can explore and learn on your own.
Note that I won’t cover how Swift works. If you have a working knowledge of, say, C#, Kotlin, Go or Rust, you’ll probably be mostly fine with a bit of supplementary web searching. Being comfortable with the command-line is essential, too.
Just to make sure your development environment is all set up,
let’s begin with the simplest of all Mac programs. Save the
following code in a Swift file named main.swift
:
import AppKit
let _ = NSApplication.shared
NSApp.setActivationPolicy(.regular)
NSApp.run()
And then compile and run it:
$ swiftc main.swift && ./main
You should see the executable appear in the Dock and in ⌘-tab!

main
executable appears in the Dock.Unfortunately, our application (if you can even call it that) has no menu bar, so you’ll need to ⌃-click it in the Dock and select “Quit” to quit it.
With that introduction out of the way, in the next part we’ll familiarize ourselves with the application structure.
All the code from this series is available on GitHub.
Luna Razzaghipour
6 May 2025