Build With Me · macOS
Build your macOS app with me.
From a software idea to a Mac app that is signed, notarized and kept up to date.
A native Mac app is built in Swift with Xcode: the interface in SwiftUI, and in AppKit where SwiftUI is not enough. But a Mac is not a large iPhone. People work on it for hours, with several windows, a menu bar, keyboard shortcuts and files they open and save. Before writing code, two decisions shape everything else: the distribution channel — the Mac App Store, which requires the sandbox, or direct distribution, signed with Developer ID and notarized — and how much system access your app really needs.
Checked on
In brief
- Language and tools
- Swift, Xcode, SwiftUI — with AppKit for what SwiftUI does not cover
- Two channels
- Mac App Store (sandbox required, App Review) or direct distribution (Developer ID + notarization)
- Apple account
- Apple Developer Program: 99 USD per membership year, or local currency where available — needed to notarize and publish
- Useful versions
- macOS 13 for MenuBarExtra and login items (SMAppService); macOS 14 for SwiftData and @Observable
- At Bynilson
- Guide and official resources; co-building or delivery reviewed case by case
Three ways to build
Learn, build it together, or have it built.
Learn and build
The path below, step by step, points each time to Apple’s official documentation. Build School teaches web products, not Swift: for a Mac app, this guide and Apple’s tutorials are the material.
Build it together
You keep the code and the decisions; the review covers architecture, distribution and security, in writing. There is no native app published in the Bynilson portfolio yet: a request is reviewed case by case, and the answer may be a referral to a specialist.
Have it built
A request describes the product, the intended distribution channel and the system access it needs. It is reviewed case by case — no package, no published price — and may lead to a scoped plan, a web alternative, or the name of a specialist studio.
No native app published in the Bynilson portfolio yet: a co-building or delivery request is reviewed case by case, and the answer may be a referral to a specialist.
01 — The Mac
What is different on a Mac
Apple’s guidelines describe someone seated 1 to 3 feet from a large display, often with several apps open, for a few minutes or several hours of focused work. The whole design follows from that.
- Several windows
- A Mac app can open several windows of the same kind (one document per window) or single windows (an inspector, a library). Their size, position and restoration on relaunch are part of the product.
- Pointer and keyboard
- Hover, right-click, multiple selection, drag and drop, shortcuts: Mac users expect to do everything from the keyboard once they know the app. An interface designed for fingers feels slow and empty.
- The menu bar
- Every important command has a place in a menu, with its shortcut. Menus also work as an index: it is where people discover what the app can do.
- Documents
- Many Mac apps create, open and save files that people store wherever they like. That is a different model from an iPhone app’s hidden storage.
- Long sessions
- An app left open all day must stay light on memory, pick up where people left off and never lose what they typed.
If you already have an iPad app, Mac Catalyst builds a Mac version from the same project. It remains an app designed for the iPad: menus, windows and pointer behaviour need adapting before it feels at home.
02 — Interface
Windows, menus, toolbars and shortcuts
SwiftUI describes a Mac app as scenes: windows, a settings scene, menus. The pieces below cover most apps.
- Windows
- WindowGroup opens as many windows as needed; Window (macOS 13) declares a single one. Default size and how a window resizes (WindowResizability, macOS 13) are declared on the scene.
- Menus and commands
- The commands modifier adds your commands to the standard menus (File, Edit…) or creates menus of your own, each with its keyboard shortcut.
- Toolbar
- Frequent actions go in the window’s toolbar (the toolbar modifier); rare ones stay in the menus.
- Settings
- The Settings scene creates the app menu’s “Settings…” window, opened with ⌘, — where Mac users look for preferences.
- Drag and drop
- draggable and dropDestination (macOS 13) move text, images or files between your views, to the Finder or from other apps.
- Accessibility
- VoiceOver, full keyboard navigation and text size are tested from the first screens. Standard SwiftUI and AppKit controls do most of the work; custom views need explicit labels.
import SwiftUI
@main
struct NotesApp: App {
@State private var library = Library()
var body: some Scene {
WindowGroup {
NotesList(library: library)
.frame(minWidth: 480, minHeight: 320)
}
.commands {
// Adds “New Note” to the File menu, with ⇧⌘N.
CommandGroup(after: .newItem) {
Button("New Note") { library.add() }
.keyboardShortcut("n", modifiers: [.command, .shift])
}
}
}
}
@Observable
final class Library {
var notes: [String] = []
func add() { notes.append("Note \(notes.count + 1)") }
}
struct NotesList: View {
let library: Library
var body: some View {
List(library.notes, id: \.self) { Text($0) }
.toolbar {
Button("New Note", systemImage: "square.and.pencil") { library.add() }
}
}
}Typechecked: Xcode 27.1, macOS SDK 27.0, target macOS 14 — 2026-10-23
The detailed rules — window sizes, menu structure, reserved shortcuts — are in the Human Interface Guidelines for macOS.
03 — Files
Opening, saving and finding files again
How your app touches files often decides its distribution channel. Settle it before the screens.
- Open and Save panels
- When someone picks a file or folder in the system panel (fileImporter / fileExporter in SwiftUI, NSOpenPanel / NSSavePanel in AppKit), macOS extends the sandbox to that item — and, for a folder, to everything inside it.
- Keeping access after relaunch
- To reopen the same file next time without asking again, the app stores a security-scoped bookmark, then wraps each access in startAccessingSecurityScopedResource and stopAccessingSecurityScopedResource.
- Document-based apps
- DocumentGroup (SwiftUI) and NSDocument (AppKit) provide the system’s document model: one window per document, Open, Save, recent documents.
- File types
- Uniform Type Identifiers declare the types your app opens or creates, so the Finder knows which files to hand it.
- The container
- A sandboxed app has full access to its own container (in ~/Library/Containers) and only to what the user grants it elsewhere.
04 — System
Background work, permissions and integrations
- Menu bar utility
- MenuBarExtra (macOS 13) puts your app in the menu bar. To keep it out of the Dock, the LSUIElement key in Info.plist declares it an “agent” app.
- Launch at login
- SMAppService (macOS 13) registers the app or a helper as a login item. On the Mac App Store, nothing may start at login or keep running after the app quits without the user’s consent (Guideline 2.4.5(iii)).
- Permissions
- Camera, microphone, screen recording, controlling other apps through accessibility, some protected folders: macOS asks the user. Explain in the interface, before the prompt, why the app needs it — and plan for a refusal.
- Integrations
- App Intents (macOS 13) exposes your actions to Shortcuts and Spotlight; WidgetKit adds widgets; share and Finder extensions connect your app to the rest of the system.
- Low-level extensions
- System extensions, drivers, administrator privileges: each capability has its own rules and entitlements. The Mac App Store forbids installing kexts or additional code (2.4.5(iv)) and escalating to root (2.4.5(v)). Verify each capability against Apple’s documentation before committing: it often decides the channel.
import SwiftUI
@main
struct FocusTimerApp: App {
@AppStorage("minutes") private var minutes = 25
var body: some Scene {
// A menu bar utility. To keep it out of the Dock, set
// LSUIElement (“Application is agent”) to YES in Info.plist.
MenuBarExtra("Focus", systemImage: "timer") {
TimerPanel(minutes: minutes)
}
.menuBarExtraStyle(.window)
// Settings… (⌘,) — the standard macOS place for preferences.
Settings {
Form {
Stepper("Session: \(minutes) min", value: $minutes, in: 5...90, step: 5)
}
.padding()
.frame(width: 320)
}
}
}
struct TimerPanel: View {
let minutes: Int
@State private var running = false
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text(running ? "Session in progress" : "Ready: \(minutes) min")
.font(.headline)
HStack {
Button(running ? "Stop" : "Start") { running.toggle() }
.keyboardShortcut(.defaultAction)
SettingsLink { Text("Settings…") }
}
Divider()
Button("Quit") { NSApplication.shared.terminate(nil) }
.keyboardShortcut("q")
}
.padding()
.frame(width: 240)
}
}Typechecked: Xcode 27.1, macOS SDK 27.0, target macOS 14 — 2026-10-23
05 — Technologies
The building blocks of a Mac app, and when to use them
SwiftUI
Apple’s declarative UI framework, shared across its platforms.
When: The default for a new app: windows, menus, settings, lists, forms.
Not when: When an advanced Mac control does not exist in SwiftUI yet — take it from AppKit.
AppKit
The long-standing Mac framework, the most complete on macOS.
When: Rich text editors, very dense tables, fine window control, existing code.
Not when: To rewrite everything on principle: it can be introduced one screen at a time.
SwiftUI + AppKit
NSViewRepresentable puts an AppKit view inside SwiftUI; NSHostingView does the reverse.
When: Almost always, at some point: on the Mac that is normal, not a failure.
SwiftData / Core Data
Local persistence: SwiftData (macOS 14) in modern Swift, Core Data for existing projects or advanced needs.
When: Structured data kept on the Mac, with or without sync.
Not when: For files the user manages: that is the document model.
Keychain
The system’s encrypted store for passwords, tokens and keys.
When: As soon as a secret is stored on the Mac — never in UserDefaults or a file.
Swift Package Manager
The dependency manager built into Xcode.
When: To add a library or split your own code into modules.
Xcode
The environment to write, test, sign and distribute.
When: Always: it produces the signed app.
Sparkle
An open-source update framework widely used outside the App Store (not published by Apple).
When: Direct distribution: check for, download and install a new signed version.
Not when: On the Mac App Store, which alone distributes updates (2.4.5(vii)).
Sparkle — open-source update framework for macOSSparkle project
Foundation Models / Core ML
Foundation Models (macOS 26) gives access to Apple Intelligence models; Core ML runs your own models on device.
When: Desktop AI tools that must keep data on the Mac.
Not when: If not all your users have an Apple Intelligence–capable Mac: Foundation Models depends on it — plan a fallback.
06 — Distribution
Mac App Store or direct distribution
On the Mac, unlike the iPhone, both channels are legitimate. They impose different rules; some apps even ship in both.
| Mac App Store | Direct distribution (Developer ID) | |
|---|---|---|
| Sandbox | Required (Guideline 2.4.5(i)) | Recommended, not required |
| Apple’s check | App Review, by people, for every version | Notarization: an automated scan, not a review of the app |
| Installation | From the App Store, no third-party installers (2.4.5(ii)) | Your file (ZIP, DMG or installer package), from your site |
| Updates | Only through the Mac App Store (2.4.5(vii)) | Your own mechanism, Sparkle for example — every version notarized |
| Payment | Apple in-app purchase to unlock features (Guideline 3.1.1) | Your own payments and licences |
| Licences | No licence screen or key at launch (2.4.5(vi)) | Up to you |
| Discovery | App Store search and pages | Your site, your SEO, your marketing |
- The app must reach files the user does not pick one by one (backup, indexing, cleanup).
- A developer tool that runs other programs or installs components.
- A privileged helper, system extension or driver, where Apple allows it outside the App Store.
- A business model built on licence keys or volume licences for companies.
- A beta channel and an update cadence you control.
These are the cases where direct distribution is a sound choice, not a workaround. In both channels the app is signed; only direct distribution needs notarization.
07 — Signing
Signing and notarizing an app distributed outside the App Store
On first launch, Gatekeeper checks that a downloaded app is signed with a Developer ID certificate and notarized by Apple. Since macOS 10.15, all software distributed with Developer ID and built after June 1, 2019 must be notarized.
- Join the Apple Developer Program: Developer ID and notarization are not available with a free account.
- Create the “Developer ID Application” certificate — only the team’s Account Holder can generate it.
- Enable the Hardened Runtime in Xcode: notarization requires it.
- Send the app to the notary service with notarytool (altool has not been accepted since November 1, 2023).
- Staple the ticket to the app with stapler, then distribute it as a ZIP or DMG.
# Once: store your notarization credentials in the Keychain.
xcrun notarytool store-credentials "notary" --apple-id "you@example.com" --team-id "TEAMID"
# Each release: zip the signed app, submit it, wait for the verdict.
ditto -c -k --keepParent "MyApp.app" "MyApp.zip"
xcrun notarytool submit "MyApp.zip" --keychain-profile "notary" --wait
# Attach the ticket to the app itself, then package it (ZIP or DMG).
xcrun stapler staple "MyApp.app"08 — Releases
Publishing, updating, keeping up with macOS
- Version numbers
- The displayed version (CFBundleShortVersionString) and the build number (CFBundleVersion) move with every release; the update channel relies on them.
- Every release notarized
- With direct distribution, every published build goes through signing, notarization and stapling again. Script it by the second release.
- Update channel
- Mac App Store: updates go through App Store Connect, and TestFlight handles the beta. Direct distribution: a signed update feed (Sparkle’s, for example) and, if needed, a separate beta channel.
- Staged rollout
- Release to a small group first, watch the crash reports, then widen — cheaper than a version you have to pull.
- Apple’s rhythm
- A new macOS ships every autumn, with betas from June. Test your app on those betas and decide which macOS versions you keep supporting.
Before you publish a release
09 — Examples
Kinds of Mac apps, and what matters for each
Category descriptions to frame your project — not Bynilson deliveries.
- Productivity
- Several windows, shortcuts for everything, restored state, sync if people own several devices.
- Menu bar utilities
- One function, always at hand: MenuBarExtra, launch at login with consent, a very small footprint.
- Desktop AI tools
- The Mac runs models locally (Core ML, Foundation Models on a compatible Mac): a strong argument when data must not leave the machine.
- File management
- Everything rests on file access: often the question that decides between the sandbox and direct distribution.
- Video and image
- Large files, long renders, lots of memory: visible progress, cancellation, background work that never freezes the interface.
- Developer tools
- Terminal, Git, external processes: they often reach outside the sandbox — see the next section.
- Business desktop apps
- Team accounts, sensitive data, rollout to many machines: distribution and updates matter as much as the interface.
- Professional workflows
- Audio, layout, analysis: file formats, shortcuts and performance are the product.
10 — Dev tools
Developer tools on the Mac
- A command-line tool
- A Swift executable (created with Swift Package Manager) is often enough. Outside the App Store it must be signed and notarized like an app.
- A menu bar app
- For a function called often without leaving the editor: a global shortcut, a status, a launcher.
- A full app
- When the tool has documents, settings and windows of its own.
For distribution, many developer tools ship as a direct download or through Homebrew, a widely used third-party package manager: options to check against your audience, not Apple channels.
11 — Cross-platform
If you also need Windows or Linux
One codebase for three systems is possible. The price is paid in app size, system integration or licences — rarely nowhere.
| Approach | What you get | What it costs |
|---|---|---|
| One native app per system | SwiftUI/AppKit on Mac, WinUI or WPF (.NET) on Windows, GTK or Qt on Linux: each app fully at home | Two or three codebases to write and maintain |
| Tauri | A Rust core and a web interface rendered by the system’s web engine: lightweight apps | Rendering depends on each system’s web engine — test on each |
| Electron | Chromium and Node.js bundled: identical rendering everywhere, a mature ecosystem | Heavier apps, in size and in memory |
| .NET (WinUI, WPF, MAUI) | Native Windows apps; MAUI also targets the Mac through Mac Catalyst | On the Mac, integration stays less refined than SwiftUI/AppKit |
| Qt | C++ or QML, Windows, macOS and Linux from one codebase | Open-source (LGPL/GPL) or commercial licence, to choose carefully |
12 — Scoping
Scope your Mac app in six questions
Distribution, file access, system integration, security, background work, offline: your answers point to the likely channel and to what to check before writing code. Nothing is stored.
Answer a question to see what applies to your app.
13 — Path
The path, from idea to first published version
Each stage points to the official resource that explains it. The stage marked “planned” does not exist yet.
- 01
Define what the app does on a Mac
One sentence: for whom, which task, why on a Mac rather than in a browser. Read the macOS design fundamentals.
AvailableDesigning for macOSApple
- 02
Choose the distribution channel
Mac App Store or Developer ID, based on the files and system access you need — section 06 and the scoping above.
AvailableDeveloper IDApple
- 03
Install Xcode and create the project
A “macOS App” project with a SwiftUI interface; running it on your own Mac works with a free Apple Account.
AvailableXcodeApple
- 04
Swift fundamentals
Types, optionals, structs and classes, closures, async/await.
- 05
SwiftUI fundamentals
Views, state, lists, navigation — Apple’s tutorials, knowing that part of them targets the iPhone.
AvailableSwiftUI TutorialsApple
- 06
Windows, menus and settings
Scenes, commands and shortcuts, the Settings scene.
AvailableCommands (menus)Apple
- 07
- 08
- 09
- 10
Configure the sandbox and entitlements
Turn on only the access you need, then test the app with it.
- 11
Test
Unit tests with Swift Testing, then the real app on the oldest supported macOS version.
AvailableSwift TestingApple
- 12
Sign and distribute
Notarization for direct distribution; App Store Connect and TestFlight for the Mac App Store.
- 13
Monitor and iterate
Crash reports, user feedback, the next version.
- 14
Bynilson walkthrough: from empty project to notarized DMG
A captioned, step-by-step screen recording. Not recorded yet.
Planned
Frequently asked questions
SwiftUI or AppKit for a new Mac app?
SwiftUI by default: windows, menus, settings, lists and forms are well expressed in it. AppKit remains the most complete Mac framework, used for advanced controls or existing code — brought into a SwiftUI app one screen at a time. Most serious Mac apps use both.
How do you distribute a Mac app?
Through the Mac App Store (sandbox required, App Review, updates through the Store) or directly from your site, with an app signed with Developer ID and notarized by Apple. Both require Apple Developer Program membership.
Mac App Store or direct distribution: which one?
The Mac App Store if your app fits in the sandbox and App Store discovery matters to you. Direct distribution if the app needs broad file or system access, if you sell licences, or if you want to control updates. The scoping on this page shows the likely channel.
How do signing and notarization work?
The app is signed with a Developer ID certificate, built with the Hardened Runtime, then sent with notarytool to Apple’s notary service, an automated scan. The resulting ticket is stapled to the app with stapler; on first launch, Gatekeeper checks it.
Can I develop a Mac app without paying?
Yes, to learn and test: with a free Apple Account, Xcode builds and runs the app on your Mac. Developer ID, notarization, TestFlight and App Store Connect require the Apple Developer Program, at 99 USD per membership year or local currency where available.
How much does it cost to develop a Mac app?
It depends mostly on files, system integration and the distribution channel — which is why no price is published here. The one certain fixed cost is the Apple membership. The project builder produces a reasoned scope and roadmap, not a quote.
Can my iPad app become a Mac app?
Mac Catalyst builds a Mac version from the same iPad project. It works, but stays designed for the iPad: menus, windows, pointer and shortcuts need adapting before it feels at home on the Mac.
Sources
- SwiftUI documentationAppleChecked on 23 Oct 2026
- AppKit documentationAppleChecked on 23 Oct 2026
- SwiftDataAppleChecked on 23 Oct 2026
- Keychain ServicesAppleChecked on 23 Oct 2026
- Swift packagesAppleChecked on 23 Oct 2026
- XcodeAppleChecked on 23 Oct 2026
- Foundation ModelsAppleChecked on 23 Oct 2026
- Designing for macOSAppleChecked on 23 Oct 2026
- Developer IDAppleChecked on 23 Oct 2026
- The Swift Programming LanguageSwift.orgChecked on 23 Oct 2026
- SwiftUI TutorialsAppleChecked on 23 Oct 2026
- Commands (menus)AppleChecked on 23 Oct 2026
- DocumentGroupAppleChecked on 23 Oct 2026
- Configuring the macOS App SandboxAppleChecked on 23 Oct 2026
- Swift TestingAppleChecked on 23 Oct 2026
- Notarizing macOS software before distributionAppleChecked on 23 Oct 2026
- Acquiring crash reports and diagnostic logsAppleChecked on 23 Oct 2026