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.
// 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) { }
}
// 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:
styleMask
: Defines appearance and controls (close, minimize, resize buttons)backing
: How content is buffered (.buffered, .retained, .nonretained)contentView
: Root NSView in the window's hierarchy