DEV Community

Henry Godnick
Henry Godnick

Posted on

I Learned Swift to Build 3 Mac Apps — Here's What No Tutorial Taught Me

Six months ago I didn't know Swift. Today I have three Mac apps live on my website, real users, and actual revenue. Here's everything the tutorials left out.

Why Swift (and Why From Scratch)

I'd been building web stuff for years. React, Node, the usual. But I wanted to build native Mac tools — things that lived in the menu bar, felt snappy, and didn't eat 400MB of RAM like every Electron app I'd ever used.

So I picked Swift. Not SwiftUI-only (that was a mistake I'll get to), but AppKit + SwiftUI hybrid. The learning curve was real.

Lesson 1: SwiftUI Is Not Ready for Everything

Every tutorial sells SwiftUI as the future. And it is — for simple layouts. But the moment you need a menu bar app, a custom NSWindow, or fine-grained control over focus behavior, you're back in AppKit land.

My first app, TokenBar, is a menu bar token counter for LLM APIs. SwiftUI's MenuBarExtra looks great in demos. In practice, I needed AppKit's NSPopover for the level of control I wanted. No tutorial mentioned this.

Takeaway: Learn both. Start with SwiftUI for views, but don't be afraid of AppKit when SwiftUI fights you.

Lesson 2: Memory Management Isn't Optional

Coming from JavaScript, I never thought about memory. In Swift, retain cycles will silently eat your app alive. My second app had a memory leak that took three days to find — a closure capturing self strongly inside a timer.

The fix was two characters: [weak self]. But finding it required Instruments, which has one of the worst UIs in Apple's toolkit.

Takeaway: Learn Instruments early. Run the Leaks profiler on day one, not after users report your app using 2GB of RAM.

Lesson 3: Distribution Outside the App Store Is a Nightmare

I chose to distribute outside the Mac App Store. Notarization, code signing, Developer ID certificates, stapling — none of this is well-documented for beginners.

My third app, Monk Mode, took longer to notarize correctly than it did to build the core feature (blocking social media feeds without blocking entire apps).

Takeaway: Budget a full day just for code signing and notarization. Set it up early in your project, not at the end.

Lesson 4: The Ecosystem Is Smaller Than You Think

npm has a package for everything. Swift Package Manager... doesn't. I had to write my own network monitoring layer, my own menu bar state management, and several UI components that would have been a single npm install in JavaScript.

This is actually a feature, not a bug. You understand your code deeply. But it's slower.

Lesson 5: Ship Before You're Ready

My biggest mistake was polishing TokenBar for weeks before showing anyone. The first version that got real feedback was rough — but the feedback shaped the product more than any amount of solo iteration would have.

I shipped all three apps within four months. They're not perfect. But they exist, they work, and people use them.

The Stack That Worked

  • Xcode (obviously, but use vim keybindings — trust me)
  • AppKit + SwiftUI hybrid for menu bar apps
  • Swift Package Manager for dependencies
  • GitHub Actions for CI (yes, it works for Mac apps)
  • Sparkle for auto-updates outside the App Store

Final Thought

If you're a web developer thinking about native Mac apps: just start. Swift is learnable. The hard parts aren't the language — they're the ecosystem quirks that no tutorial covers. Build something small, ship it, and learn the rest as you go.

The worst that happens is you build something nobody wants. The best that happens is you build something you use every day.


I'm a solo dev building Mac utilities. TokenBar tracks your LLM token spending in real time (tokenbar.site), and Monk Mode blocks distracting feeds without blocking entire apps (mac.monk-mode.lifestyle).

Top comments (0)