--- id: ios-mac-catalyst-patterns title: Mac Catalyst — iOS 앱을 Mac 으로 category: Coding status: draft source_trust_level: B verification_status: conceptual created_at: 2026-05-09 updated_at: 2026-05-09 tags: [ios, macos, catalyst, vibe-coding] tech_stack: { language: "Swift / SwiftUI", applicable_to: ["iOS", "macOS"] } applied_in: [] aliases: [Mac Catalyst, Mac idiom, designed for iPad, multi-platform Swift] --- # Mac Catalyst > iPad 앱 → Mac 으로 minimal effort 포팅. **하나의 코드베이스, Mac native 느낌**. 단 비-Apple Silicon Intel + macOS 가 필요하면 native macOS app 고려. SwiftUI 가 새 표준 (multi-platform). ## 📖 핵심 개념 - "Designed for iPad": 그대로 (Apple Silicon Mac 만, no work). - Mac Catalyst: 일부 코드 + Mac UI 적응. - Native AppKit: 가장 강력 + 별 코드. - SwiftUI multi-platform: 한 codebase 모든 platform. ## 💻 코드 패턴 ### Mac Catalyst 활성 ``` Xcode → Target → General → Supported Destinations → Add "Mac Catalyst" 또는 "Mac (Designed for iPad)" — 사용자가 그대로 받음 ``` ### Optimize for Mac ``` Build Settings → "Optimize Interface for Mac" = YES - AppKit 비슷 controls - macOS native fonts - 더 작은 사이즈 ``` ### conditional compile ```swift #if targetEnvironment(macCatalyst) button.preferredBehavioralStyle = .pad // Mac 에서 더 작게 #endif ``` ```swift // SwiftUI #if os(macOS) || targetEnvironment(macCatalyst) .frame(minWidth: 600, minHeight: 400) #endif ``` ### Toolbar (Mac native) ```swift NavigationStack { ContentView() .toolbar { ToolbarItem(placement: .primaryAction) { Button("Add") { ... } } } } ``` Mac 에선 자동으로 NSToolbar 로. ### Menu bar ```swift @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } .commands { CommandGroup(replacing: .newItem) { Button("New Document") { ... } .keyboardShortcut("n") } CommandMenu("Custom") { Button("Action") { ... } .keyboardShortcut("a", modifiers: [.command, .shift]) } } } } ``` ### Window settings (Mac) ```swift .windowResizability(.contentSize) .defaultSize(width: 800, height: 600) #if os(macOS) .windowToolbarStyle(.unifiedCompact) #endif ``` ### NSWindow 직접 (Catalyst → AppKit bridge) ```swift // CatalystAppKitBridge — bridging SPM package import AppKit func setMacWindow() { NSApplication.shared.windows.first?.titlebarAppearsTransparent = true } ``` 복잡 — 그냥 SwiftUI 권장. ### 입력 (마우스 + 키보드) ```swift struct ItemRow: View { @State var hovered = false var body: some View { HStack { ... } .onHover { hovered = $0 } .background(hovered ? Color.accentColor.opacity(0.1) : .clear) .onTapGesture(count: 2) { /* double click */ } } } ``` ### Drag & drop ```swift .draggable(item.id.uuidString) .dropDestination(for: String.self) { ids, location in // process return true } ``` ### File access (Mac 답게) ```swift .fileImporter(isPresented: $show, allowedContentTypes: [.plainText]) { result in // ... } .fileExporter(isPresented: $show, document: doc, contentType: .plainText) { result in // ... } ``` ### Multi-window ```swift WindowGroup(id: "editor", for: Document.ID.self) { $id in EditorView(id: id ?? UUID()) } @Environment(\.openWindow) var open Button("New") { open(id: "editor", value: UUID()) } ``` ## 🤔 의사결정 기준 | 상황 | 추천 | |---|---| | iPad 앱 + Apple Silicon Mac 만 | "Designed for iPad" (zero work) | | iPad + Mac 사용자 둘 다 | Mac Catalyst + Optimize for Mac | | Mac 우선 + 강력 native | SwiftUI multi-platform | | 매우 Mac-specific | Native AppKit | | Game | SpriteKit / Metal (둘 다 Catalyst OK) | ## ❌ 안티패턴 - **iPad UI 그대로**: Mac 사용자 어색. toolbar / menu / shortcut 추가. - **Touch-only gesture 의존**: Mac 마우스 호환 X. - **Window 가 작은 화면 가정**: resizable + min size. - **App icon 정사각만**: Mac 은 둥근 corner — 별도 icon. - **Keyboard shortcut 누락**: Mac UX 핵심. - **NSAppKit 직접 + Catalyst**: 어려움 — SwiftUI / 별도 macOS target. - **Universal binary 의 Catalyst 만**: x86 arch 누락. ## 🤖 LLM 활용 힌트 - iPad 앱 = "Designed for iPad" 부터. - 진심 Mac = Catalyst + Optimize for Mac + toolbar/menu. - Mac native = SwiftUI multi-platform. ## 🔗 관련 문서 - [[iOS_SwiftUI_State_Property_Wrappers]] - [[iOS_Universal_Links_Deep_Linking]] - [[Cross_Platform_Theming]]