appkit-bridge
AppKit Bridge — SwiftUI ↔ AppKit Integration
Critical Constraints
- ❌ DO NOT use
NSViewControlleras app architecture → ✅ Use SwiftUIApp+Scene, bridge only where needed - ❌ DO NOT use
NSViewsubclass when SwiftUI modifier exists → ✅ Check SwiftUI first, bridge as last resort - ❌ DO NOT forget
makeCoordinator()for delegate callbacks → ✅ Use Coordinator pattern for NSViewRepresentable - ❌ DO NOT call
makeNSViewto update → ✅ UseupdateNSView(_:context:)for state changes
NSViewRepresentable (AppKit → SwiftUI)
import SwiftUI
import AppKit
struct WrappedNSView: NSViewRepresentable {
var text: String
func makeNSView(context: Context) -> NSTextField {
let field = NSTextField()
field.delegate = context.coordinator
return field
}
func updateNSView(_ nsView: NSTextField, context: Context) {
nsView.stringValue = text
}
func makeCoordinator() -> Coordinator { Coordinator(self) }
class Coordinator: NSObject, NSTextFieldDelegate {
var parent: WrappedNSView
init(_ parent: WrappedNSView) { self.parent = parent }
func controlTextDidChange(_ obj: Notification) {
// Handle text changes
}
}
}
NSHostingView (SwiftUI → AppKit)
let swiftUIView = MySwiftUIView()
let hostingView = NSHostingView(rootView: swiftUIView)
hostingView.translatesAutoresizingMaskIntoConstraints = false
// Add to AppKit view hierarchy
parentView.addSubview(hostingView)
NSLayoutConstraint.activate([
hostingView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor),
hostingView.trailingAnchor.constraint(equalTo: parentView.trailingAnchor),
hostingView.topAnchor.constraint(equalTo: parentView.topAnchor),
hostingView.bottomAnchor.constraint(equalTo: parentView.bottomAnchor),
])
NSPanel — Floating Window
class FloatingPanel: NSPanel {
init(contentView: NSView) {
super.init(
contentRect: NSRect(x: 0, y: 0, width: 600, height: 400),
styleMask: [.nonactivatingPanel, .titled, .closable, .fullSizeContentView],
backing: .buffered, defer: true
)
titlebarAppearsTransparent = true
titleVisibility = .hidden
isOpaque = false
backgroundColor = .clear
level = .floating
collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .transient]
isMovableByWindowBackground = true
hidesOnDeactivate = false
self.contentView = contentView
center()
}
override var canBecomeKey: Bool { true }
override var canBecomeMain: Bool { false }
}
// Host SwiftUI content
let panel = FloatingPanel(contentView: NSHostingView(rootView: MyView()))
Show/Hide with Animation
extension FloatingPanel {
func showCentered() {
center()
alphaValue = 0
makeKeyAndOrderFront(nil)
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 0.15
ctx.timingFunction = CAMediaTimingFunction(name: .easeOut)
animator().alphaValue = 1
}
}
func hideAnimated() {
NSAnimationContext.runAnimationGroup({ ctx in
ctx.duration = 0.1
ctx.timingFunction = CAMediaTimingFunction(name: .easeIn)
animator().alphaValue = 0
}, completionHandler: { self.orderOut(nil) })
}
}
NSPopover
let popover = NSPopover()
popover.contentViewController = NSHostingController(rootView: PopoverContent())
popover.behavior = .transient
popover.show(relativeTo: button.bounds, of: button, preferredEdge: .minY)
popover.contentViewController?.view.window?.makeKey()
Window Positioning
extension NSPanel {
func centerOnActiveScreen() {
guard let screen = NSScreen.main ?? NSScreen.screens.first else { return }
let frame = screen.visibleFrame
setFrameOrigin(NSPoint(x: frame.midX - self.frame.width / 2,
y: frame.midY - self.frame.height / 2))
}
}
Decision Tree
Need a floating overlay? → NSPanel + NSHostingView
Need a menu bar popover? → NSPopover + NSHostingController
Need custom window chrome? → NSWindow subclass + titlebarAppearsTransparent
Need AppKit control in SwiftUI? → NSViewRepresentable
Need SwiftUI view in AppKit? → NSHostingView or NSHostingController
Need glass effect in AppKit? → NSGlassEffectView (see liquid-glass skill)
References
More from makgunay/claude-swift-skills
macos-app-structure
macOS application architecture patterns covering App protocol (@main), Scene types (WindowGroup, Window, Settings, MenuBarExtra), multi-window management, NSApplicationDelegateAdaptor for AppKit lifecycle hooks, Info.plist configuration (LSUIElement for menu bar apps, NSAccessibilityUsageDescription), entitlements for sandbox/hardened runtime, and project structure conventions. Use when scaffolding a new macOS app, configuring scenes and windows, setting up menu bar apps, or resolving macOS-specific lifecycle issues. Corrects the common LLM mistake of generating iOS-only app structures.
31macos-permissions
macOS permission handling for Accessibility (AXIsProcessTrusted), Screen Recording, Full Disk Access, input monitoring, camera, microphone, location, and contacts. Covers TCC (Transparency Consent and Control) database, graceful degradation when permissions are denied, permission prompting patterns, opening System Settings to the correct pane, detecting permission changes, and the privacy manifest (PrivacyInfo.xcprivacy) requirement. Use when implementing features that require system permissions, building permission onboarding flows, or handling denied permissions gracefully.
17swiftui-core
Core SwiftUI patterns for macOS and iOS development including navigation (NavigationSplitView, NavigationStack), state management (@State, @Binding, @Environment, @Bindable with @Observable), the new customizable toolbar system (toolbar IDs, ToolbarSpacer, DefaultToolbarItem, searchToolbarBehavior, matchedTransitionSource, sharedBackgroundVisibility), styled text editing (TextEditor with AttributedString, AttributedTextSelection, transformAttributes, textFormattingDefinition), and layout patterns. Use when building any SwiftUI view, implementing navigation, managing state, creating toolbars, or building rich text editors. Corrects common LLM errors like using deprecated NavigationView, wrong state wrappers, and outdated toolbar APIs.
14global-hotkeys
System-wide keyboard shortcut registration on macOS using NSEvent monitoring (simple, app-level) and Carbon EventHotKey API (reliable, system-wide). Covers NSEvent.addGlobalMonitorForEvents and addLocalMonitorForEvents, CGEvent tap for keystroke simulation, Carbon RegisterEventHotKey for system-wide hotkeys, modifier flag handling (.deviceIndependentFlagsMask), common key code mappings, debouncing, Accessibility permission requirements (AXIsProcessTrusted), and SwiftUI .onKeyPress for in-app shortcuts. Use when implementing global keyboard shortcuts, hotkey-triggered panels, or system-wide key event monitoring.
11swiftui-webkit
Native SwiftUI WebKit integration with the new WebView struct and WebPage observable class. Covers WebView creation from URLs, WebPage for navigation control and state management, JavaScript execution (callJavaScript with arguments and content worlds), custom URL scheme handlers, navigation management (load, reload, back/forward), navigation decisions, text search (findNavigator), content capture (snapshots, PDF generation, web archives), and configuration (data stores, user agents, JS permissions). Use when embedding web content in SwiftUI apps instead of the old WKWebView + UIViewRepresentable/NSViewRepresentable bridge pattern. This is a brand new API — do NOT use the old WKWebView wrapping approach.
10liquid-glass
Comprehensive guide to Apple's Liquid Glass design system introduced in macOS 26, iOS 26, and across all Apple platforms. Covers SwiftUI (.glassEffect(), GlassEffectContainer, .interactive(), .tint(), glassEffectID morphing, .buttonStyle(.glass), .buttonStyle(.glassProminent), glassEffectUnion), AppKit (NSGlassEffectView, NSGlassEffectContainerView), UIKit (UIGlassEffect, UIGlassContainerEffect, UIScrollEdgeEffect), and WidgetKit (accented rendering mode, widgetAccentable). Use whenever building UI with the new Apple design language, adopting glass effects, styling buttons or toolbars, or creating modern macOS/iOS interfaces. Always consult this skill when asked about new Apple design.
10