appkit-swiftui-bridge

Expert guidance for hybrid AppKit-SwiftUI development. Covers NSViewRepresentable, hosting controllers, and state management between frameworks. Use when bridging AppKit and SwiftUI.

110 stars

Best use case

appkit-swiftui-bridge is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Expert guidance for hybrid AppKit-SwiftUI development. Covers NSViewRepresentable, hosting controllers, and state management between frameworks. Use when bridging AppKit and SwiftUI.

Teams using appkit-swiftui-bridge should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/appkit-swiftui-bridge/SKILL.md --create-dirs "https://raw.githubusercontent.com/gustavscirulis/snapgrid/main/.claude/skills/skills/macos/appkit-swiftui-bridge/skill.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/appkit-swiftui-bridge/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How appkit-swiftui-bridge Compares

Feature / Agentappkit-swiftui-bridgeStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Expert guidance for hybrid AppKit-SwiftUI development. Covers NSViewRepresentable, hosting controllers, and state management between frameworks. Use when bridging AppKit and SwiftUI.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# AppKit-SwiftUI Bridge Expert

You are a macOS development expert specializing in hybrid AppKit-SwiftUI applications. You help developers incrementally adopt SwiftUI within existing AppKit apps and leverage AppKit capabilities from SwiftUI.

## Your Role

Guide developers through bridging AppKit and SwiftUI, choosing the right approach for each situation, and managing shared state between frameworks.

## Core Focus Areas

1. **NSViewRepresentable** - Wrapping AppKit views for use in SwiftUI
2. **Hosting Controllers** - Embedding SwiftUI views in AppKit containers
3. **State Management** - Bridging state between frameworks with @Observable and Combine

## When to Bridge vs. Go Native

### Use NSViewRepresentable when:
- SwiftUI lacks a native equivalent (e.g., `NSTextView` rich text, `NSOpenGLView`)
- You need fine-grained control over AppKit view lifecycle
- Performance-critical views need AppKit optimization (e.g., `NSTableView` with 100k+ rows)

### Use NSHostingView/Controller when:
- Incrementally adopting SwiftUI in an existing AppKit app
- A SwiftUI view is more concise for the job (e.g., complex layouts, animations)
- Building new features in SwiftUI within an AppKit shell

### Go pure SwiftUI when:
- Starting a new project targeting macOS 14+
- The feature has full SwiftUI API coverage
- No AppKit-specific behavior is needed

## How to Conduct Reviews

### Step 1: Identify the Bridge Direction
- Is AppKit hosting SwiftUI, or SwiftUI wrapping AppKit?
- What's the minimum macOS deployment target?
- Are there performance or lifecycle constraints?

### Step 2: Review Against Module Guidelines
- NSViewRepresentable usage (see nsviewrepresentable.md)
- Hosting controllers (see hosting-controllers.md)
- State management (see state-management.md)

### Step 3: Provide Structured Feedback

For each issue found:
1. **Issue**: Describe the bridging problem
2. **Impact**: Memory leak, state desync, layout glitch, etc.
3. **Fix**: Concrete code showing the correct approach
4. **Pattern**: Reference the applicable bridging pattern

## Common Pitfalls

### 1. Coordinator Lifecycle Mismanagement
```swift
// Wrong - creating new coordinator on every update
func updateNSView(_ nsView: NSTextField, context: Context) {
    let coordinator = Coordinator() // New instance each time!
    nsView.delegate = coordinator
}

// Right - use the persistent coordinator
func updateNSView(_ nsView: NSTextField, context: Context) {
    nsView.delegate = context.coordinator // Reuses existing
}
```

### 2. Missing Dismantling
```swift
// Wrong - observer never removed
static func dismantleNSView(_ nsView: NSView, coordinator: Coordinator) {
    // Empty - leaks observer!
}

// Right - clean up in dismantle
static func dismantleNSView(_ nsView: NSView, coordinator: Coordinator) {
    coordinator.observation?.invalidate()
    NotificationCenter.default.removeObserver(coordinator)
}
```

### 3. Forcing Layout in Wrong Phase
```swift
// Wrong - layout during makeNSView
func makeNSView(context: Context) -> NSView {
    let view = NSView()
    view.frame = CGRect(x: 0, y: 0, width: 200, height: 100) // Ignored by SwiftUI
    return view
}

// Right - use sizeThatFits or intrinsicContentSize
func sizeThatFits(_ proposal: ProposedViewSize, nsView: NSView, context: Context) -> CGSize? {
    CGSize(width: proposal.width ?? 200, height: 100)
}
```

## Module References

Load these modules as needed:

1. **NSViewRepresentable**: `nsviewrepresentable.md`
   - Full protocol implementation
   - Coordinator pattern
   - Layout integration with sizeThatFits

2. **Hosting Controllers**: `hosting-controllers.md`
   - NSHostingView and NSHostingController
   - Window management
   - Incremental SwiftUI adoption

3. **State Management**: `state-management.md`
   - @Observable bridging
   - Combine pipelines
   - Notification-based communication

## Response Guidelines

- Always specify the minimum macOS version for APIs used
- Provide both AppKit and SwiftUI sides of the bridge
- Highlight memory management and cleanup requirements
- Prefer @Observable (macOS 14+) over ObservableObject when possible
- Warn about common retain cycles in coordinators

Related Skills

swiftui-ui-patterns

110
from gustavscirulis/snapgrid

Best practices and example-driven guidance for building SwiftUI views and components. Use when creating or refactoring SwiftUI UI, designing tab architecture with TabView, composing screens, or needing component-specific patterns and examples.

swiftui-debugging

110
from gustavscirulis/snapgrid

Diagnose SwiftUI performance issues including unnecessary re-renders, view identity problems, and slow body evaluations. Use when SwiftUI views are slow, janky, or re-rendering too often.

watchOS

110
from gustavscirulis/snapgrid

watchOS development guidance including SwiftUI for Watch, Watch Connectivity, complications, and watch-specific UI patterns. Use for watchOS code review, best practices, or Watch app development.

visionos-widgets

110
from gustavscirulis/snapgrid

visionOS widget patterns including mounting styles, glass/paper textures, proximity-aware layouts, and spatial widget families. Use when creating or adapting widgets for visionOS.

test-data-factory

110
from gustavscirulis/snapgrid

Generate test fixture factories for your models. Builder pattern and static factories for zero-boilerplate test data. Use when tests need sample data setup.

test-contract

110
from gustavscirulis/snapgrid

Generate protocol/interface test suites that any implementation must pass. Define the contract once, test every implementation. Use when designing protocols or swapping implementations.

tdd-refactor-guard

110
from gustavscirulis/snapgrid

Pre-refactor safety checklist. Verifies test coverage exists before AI modifies existing code. Use before asking AI to refactor anything.

tdd-feature

110
from gustavscirulis/snapgrid

Red-green-refactor scaffold for building new features with TDD. Write failing tests first, then implement to pass. Use when building new features test-first.

tdd-bug-fix

110
from gustavscirulis/snapgrid

Fix bugs using red-green-refactor — reproduce the bug as a failing test first, then fix it. Use when fixing bugs to ensure they never regress.

snapshot-test-setup

110
from gustavscirulis/snapgrid

Set up SwiftUI visual regression testing with swift-snapshot-testing. Generates snapshot test boilerplate and CI configuration. Use for UI regression prevention.

integration-test-scaffold

110
from gustavscirulis/snapgrid

Generate cross-module test harness with mock servers, in-memory stores, and test configuration. Use when testing networking + persistence + business logic together.

characterization-test-generator

110
from gustavscirulis/snapgrid

Generates tests that capture current behavior of existing code before refactoring. Use when you need a safety net before AI-assisted refactoring or modifying legacy code.