{
    "format": "skillpro/v1",
    "skill_id": "dpearson2699-swift-ios-skills-skills-swiftui-navigation-skill-md",
    "name": "swiftui-navigation",
    "version": "1.0.0",
    "description": "Implement SwiftUI navigation patterns including NavigationStack, NavigationSplitView, sheet presentation, tab-based navigation, and deep linking. Use when building push navigation, programmatic routing, multi-column layouts, modal sheets, tab bars, universal links, or custom URL scheme handling.",
    "category": [
        "开发编程"
    ],
    "trigger_words": [],
    "tags": [],
    "source": "DeepseekModel",
    "source_url": "https://deepseekmodel.com/skill?id=dpearson2699-swift-ios-skills-skills-swiftui-navigation-skill-md",
    "exported_at": "2026-09-17T16:00:51+08:00",
    "system_prompt": "name swiftui-navigation description Implement SwiftUI navigation patterns including NavigationStack, NavigationSplitView, sheet presentation, tab-based navigation, and deep linking. Use when building push navigation, programmatic routing, multi-column layouts, modal sheets, tab bars, universal links, or custom URL scheme handling. SwiftUI Navigation Navigation patterns for SwiftUI apps targeting iOS 26+ with Swift 6.3. Covers push navigation, multi-column layouts, sheet presentation, tab architecture, and deep linking. Patterns are backward-compatible to iOS 17 unless noted. Contents NavigationStack (Push Navigation) NavigationSplitView (Multi-Column) Sheet Presentation Tab-Based Navigation Deep Links Common Mistakes Review Checklist References NavigationStack (Push Navigation) Use NavigationStack with a typed [Route] binding for programmatic push navigation. Define routes as a Hashable enum and map them with .navigationDestination(for:) ; this keeps the path compile-time checked. Use NavigationPath only when one stack must hold heterogeneous route value types. enum Route : Hashable { case item(id: Item . ID ) } struct ContentView : View { @State private var path: [ Route ] = [] let items: [ Item ] var body: some View { NavigationStack (path: $path ) { List (items) { item in NavigationLink (value: Route .item(id: item.id)) { ItemRow (item: item) } } .navigationDestination(for: Route . self ) { route in switch route { case .item( let id): DetailView (itemID: id) } } .navigationTitle( \"Items\" ) } } } Programmatic navigation: path.append(.item(id: item.id)) // Push path.removeLast() // Pop one path = [] // Pop to root Router pattern: For apps with complex navigation, use a router object that owns the path and sheet state. Each tab gets its own router instance injected via .environment() . Centralize destination mapping with a single .navigationDestination(for:) block or a shared withAppRouter() modifier. See references/navigationstack.md for full router examples including per-tab stacks, centralized destination mapping, and generic tab routing. NavigationSplitView (Multi-Column) Use NavigationSplitView for sidebar-detail layouts on iPad and Mac. Falls back to stack navigation on iPhone. struct MasterDetailView : View { @State private var selectedItem: Item ? var body: some View { NavigationSplitView { List (items, selection: $selectedItem ) { item in NavigationLink (value: item) { ItemRow (item: item) } } .navigationTitle( \"Items\" ) } detail: { if let item = selectedItem { ItemDetailView (item: item) } else { ContentUnavailableView ( \"Select an Item\" , systemImage: \"sidebar.leading\" ) } } } } Custom Split Column (Manual HStack) For custom multi-column layouts (e.g., a dedicated notification column independent of selection), use a manual HStack split with horizontalSizeClass checks: @MainActor struct AppView : View { @Environment (\\.horizontalSizeClass) private var horizontalSizeClass @AppStorage ( \"showSecondaryColumn\" ) private var showSecondaryColumn = true var body: some View { HStack (spacing: 0 ) { primaryColumn if shouldShowSecondaryColumn { Divider ().edgesIgnoringSafeArea(.all) secondaryColumn } } } private var shouldShowSecondaryColumn: Bool { horizontalSizeClass == .regular && showSecondaryColumn } private var primaryColumn: some View { TabView { /* tabs */ } } private var secondaryColumn: some View { NotificationsTab () .environment(\\.isSecondaryColumn, true ) .frame(maxWidth: .secondaryColumnWidth) } } Use the manual HStack split when you need full control or a non-standard secondary column. Use NavigationSplitView when you want a standard system layout with minimal customization. Sheet Presentation Prefer .sheet(item:) over .sheet(isPresented:) when state represents a selected model. Sheets should own their actions and call dismiss() internally. @State private var selectedItem: Item ? .sheet(item: $selectedItem ) { item in EditItemSheet (item: item) } Presentation sizing (iOS 18+): Control sheet dimensions with .presentationSizing : .sheet(item: $selectedItem ) { item in EditItemSheet (item: item) .presentationSizing(.form) // .form, .page, .fitted, .automatic } PresentationSizing values: .automatic -- platform default .page -- roughly paper size, for informational content .form -- slightly narrower than page, for form-style UI .fitted -- sized by the content's ideal size Fine-tuning: .fitted(horizontal:vertical:) constrains fitting axes; .sticky(horizontal:vertical:) grows but does not shrink in specified dimensions. Dismissal protection: On iOS/iPadOS, use .interactiveDismissDisabled(hasUnsavedChanges) and provide explicit Save/Discard actions inside the sheet. On macOS 15+, use .dismissalConfirmationDialog(\"Discard?\", shouldPresent: hasUnsavedChanges) for window dismissal confirmation. Route every programmatic close through the same save/validate/discard gate; interactiveDismissDisabled guards interactive dismissal only. Enum-driven sheet routing: Define a SheetDestination enum that is Identifiable , store it on the router, and map it with a shared view modifier. This lets any child view present sheets without prop-drilling. See references/sheets.md for the full centralized sheet routing pattern. Tab-Based Navigation Use the Tab API with a selection binding for scalable tab architecture. Each tab should wrap its content in an independent NavigationStack . struct MainTabView : View { @State private var selectedTab: AppTab = .home var body: some View { TabView (selection: $selectedTab ) { Tab ( \"Home\" , systemImage: \"house\" , value: .home) { NavigationStack { HomeView () } } Tab ( \"Search\" , systemImage: \"magnifyingglass\" , value: .search) { NavigationStack { SearchView () } } Tab ( \"Profile\" , systemImage: \"person\" , value: .profile) { NavigationStack { ProfileView () } } } } } Custom binding with side effects: Route selection changes through a function to intercept special tabs (e.g., compose) that should trigger an action instead of changing selection. iOS 26 Tab Additions Tab(value:role:) with .search -- marks a dedicated search tab with system default search title, icon, and pinning behavior .tabViewSearchActivation(_:) -- controls search tab activation and deactivation behavior .tabBarMinimizeBehavior(_:) -- .onScrollDown , .onScrollUp , .never (iPhone only) .tabViewSidebarHeader/Footer -- customize sidebar sections on iPadOS/macOS .tabViewBottomAccessory { } -- attach content below the tab bar (e.g., Now Playing bar) TabSection -- group tabs into sidebar sections with .tabPlacement(.sidebarOnly) See references/tabview.md for full TabView patterns including custom bindings, dynamic tabs, and sidebar customization. Deep Links Use parse → validate → commit. Parse into a typed route without mutating navigation; validate scheme/host/path, identifier shape, authorization, and destination existence; then update tab/path atomically. Invalid links must leave the current navigation unchanged. Universal Links Universal links let iOS open your app for standard HTTPS URLs. They require: An Apple App Site Association (AASA) file at /.well-known/apple-app-site-association An Associated Domains entitlement ( applinks:example.com ) Handle Universal Links and custom URL schemes in SwiftUI with .onOpenURL : @main struct MyApp : App { @State private var router = Router () var body: some Scene { WindowGroup { ContentView () .environment(router) .onOpenURL { url in router.handle(url: url) } } } } Custom URL Schemes Register schemes in Info.plist under CFBundleURLTypes . Handle with .onOpenURL . Prefer universal links over custom schemes for publicly shared links -- they provide web fallback and domain verification. Handoff (NSUserActivity) Advertise activities with .userActivity() and receive Handoff or other user activities with .onContinueUserActivity() . Declare activity types in Info.plist under NSUserActivityTypes . Set isEligibleForHandoff = true and provide a webpageURL as fallback. See references/deeplinks.md for full examples of AASA configuration, router URL handling, custom URL schemes, and NSUserActivity continuation. Common Mistakes Using deprecated NavigationView -- use NavigationStack or NavigationSplitView Sharing one navigation path or router across all tabs -- each tab needs its own path Using .sheet(isPresented:) when state represents a model -- use .sheet(item:) instead Storing view instances in navigation paths -- store lightweight Hashable route data Nesting @Observable router objects inside other @Observable objects Prefer Tab(value:) with TabView(selection:) over the older .tabItem { } API Assuming tabBarMinimizeBehavior works on iPad -- it is iPhone only Handling deep links in multiple places -- centralize URL parsing in the router Hard-coding sheet frame dimensions -- use .presentationSizing(.form) instead Missing @MainActor on router classes -- required for Swift 6 concurrency safety Review Checklist NavigationStack used (not NavigationView ) Each tab has its own NavigationStack with independent path Route enum is Hashable with stable identifiers .navigationDestination(for:) maps all route types .sheet(item:) preferred over .sheet(isPresented:) Sheets own their dismiss logic internally Router object is @MainActor and @Observable Deep link URLs parsed and validated before navigation Universal links have AASA and Associated Domains configured Tab selection uses Tab(value:) with binding References NavigationStack and router patterns: references/navigationstack.md Sheet presentation and routing: references/sheets.md TabView patterns and iOS 26 API: references/tabview.md Deep links, universal links, and Handoff: references/deeplinks.md Architecture and state management: see swiftui-patterns skill Layout and components: see swiftui-layout-components skill",
    "model_config": {
        "provider": "deepseek",
        "model": "deepseek-chat",
        "temperature": 0.7,
        "max_tokens": 4096,
        "top_p": 0.9
    },
    "examples": [
        {
            "input": "请用swiftui-navigation帮我处理问题",
            "output": "好的，我是swiftui-navigation。Implement SwiftUI navigation patterns including NavigationStack, NavigationSplitView, sheet presentation, tab-based navigation, and deep linking. Use when building push navigation, programmatic routing, multi-column layouts, modal sheets, tab bars, universal links, or custom URL scheme handling. 我会根据你的需求提供专业帮助。"
        },
        {
            "input": "介绍一下你的能力",
            "output": "我是swiftui-navigation，专注于开发编程领域。Implement SwiftUI navigation patterns including NavigationStack, NavigationSplitView, sheet presentation, tab-based navigation, and deep linking. Use when building push navigation, programmatic routing, multi-column layouts, modal sheets, tab bars, universal links, or custom URL scheme handling."
        }
    ],
    "install_guide": {
        "coze": "在 Coze 平台创建 Bot -> 技能配置 -> 导入此 .skill 文件",
        "dify": "在 Dify 平台创建应用 -> 添加知识库 -> 导入此 .skill 配置",
        "claude": "将 system_prompt 字段内容复制到 Claude 自定义指令中",
        "custom": "将此 .skill 文件加载到你的 AI Agent 框架中，解析 system_prompt 和 model_config 即可使用"
    },
    "scripts": {
        "python": "# swiftui-navigation - Python extension\n# Add custom Python logic here\ndef process(input_data):\n    return input_data\n",
        "javascript": "// swiftui-navigation - JavaScript extension\n// Add custom JS logic here\nfunction process(inputData) {\n    return inputData;\n}\n"
    },
    "tools": {
        "mcp_servers": [],
        "api_endpoints": []
    },
    "dependencies": {
        "python": [],
        "node": []
    },
    "hooks": {
        "on_load": "echo \"Skill loaded: swiftui-navigation\"",
        "on_call": "",
        "on_error": "echo \"Skill error: please check logs\""
    }
}