iOS vs macOS - Developer Cheat Sheet

Critical Framework Differences

AppKit vs UIKit vs SwiftUI

Framework Platform Key Classes Programming Model Maturity Event Handling
AppKit macOS only NSApplication, NSWindow, NSView, NSViewController, NSMenu Imperative, verbose, multi-window native Very Mature (NeXTSTEP roots) Mouse, Keyboard, Trackpad
UIKit iOS/Catalyst UIApplication, UIWindow, UIView, UIViewController Imperative, touch-first, single-window focus Mature (iPhoneOS 1) Touch, Gestures
SwiftUI Cross-platform View protocol, WindowGroup, NavigationSplitView Declarative, platform-adaptive Maturing (iOS 13/macOS 10.15) Gesture modifiers, .onHover

Critical: NSWindow is NOT a subclass of NSView (unlike UIWindow/UIView). NS-prefixed classes are NOT direct equivalents of UI-prefixed classes.

Framework Interoperability

// Embed SwiftUI in AppKit
let hostingView = NSHostingView(rootView: MySwiftUIView())
parentView.addSubview(hostingView)

// Embed AppKit in SwiftUI
struct AppKitViewWrapper: NSViewRepresentable {
    func makeNSView(context: Context) -> NSTextField { NSTextField() }
    func updateNSView(_ nsView: NSTextField, context: Context) { }
}

struct AppKitControllerWrapper: NSViewControllerRepresentable {
    func makeNSViewController(context: Context) -> MyViewController { MyViewController() }
    func updateNSViewController(_ nsViewController: MyViewController, context: Context) { }
}

macOS-Specific UI Paradigms

Window Management (macOS-Specific)

NSWindow & NSWindowController

// NSWindow is NOT an NSView subclass
let window = NSWindow(contentRect: rect,
                     styleMask: [.titled, .resizable, .closable, .miniaturizable],
                     backing: .buffered, defer: false)
window.contentView = myRootView

Key NSWindow Properties: