You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过SwiftUI NavigationLinks实现嵌套JSON的四级导航跳转

SwiftUI 实现本地JSON驱动的多级导航钻取

问题描述

首先说明:我确信该问题大概率存在简易解决方案,若属实在此先行致歉,但我耗费3天查阅大量技术文章、观看开发教程仍未找到解决思路,因此发帖求助。

核心需求:使用SwiftUI的NavigationView/NavigationLink组件,读取本地JSON文件数据实现四级视图钻取导航。应用逻辑类似常规购物菜单:前三级从主分类开始逐层下钻到子分类,最终抵达第四级产品详情页,展示所选产品的品牌、型号、产品编码等完整信息。

目前我已完成JSON数据模型设计,构建了对应数据结构体,通过Decodable协议实现数据绑定,相关代码如下:

JSON 代码

{
  "appliances": [
    {
      "id": 1,
      "title": "Washing Machines",
      "machines": [
        {
          "make": "Samsung",
          "model": "Series 5 ecobubble",
          "code": 645266
        },
        {
          "make": "AEG",
          "model": "Soft Water L9FEC966R",
          "code": 674801
        },
        {
          "make": "BOSCH",
          "model": "Serie 4 WAN28281GB",
          "code": 630539
        }
      ]
    },
    {
      "id": 2,
      "title": "Washer Dryers",
      "machines": [
        {
          "make": "HAIER",
          "model": "i-Pro Series 7 HWD100-B14979S",
          "code": 633616
        },
        {
          "make": "HISENSE",
          "model": "WDQY9014EVJM",
          "code": 677089
        }
      ]
    }
  ]
}

数据模型代码

struct Appliances: Decodable {
    let appliances: [Appliance]
}

struct Appliance: Decodable, Identifiable {
    let id: Int
    let title: String
    let machines: [Machine]
}

struct Machine: Decodable {
    let make: String
    let model: String
    let code: Int
}

let appliances: Appliances = load("jsonAppliances.json")

func load<T: Decodable>(_ file: String) -> T {
    guard let jsonPath = Bundle.main.url(forResource: file, withExtension: nil) else {
        fatalError("error getting file path")
    }

    guard let jsonData = try? Data(contentsOf: jsonPath) else {
        fatalError("Error generating Data object")
    }

    let decoder = JSONDecoder()
    do {
        let appliances = try decoder.decode(T.self, from: jsonData)
        return appliances
    } catch {
        fatalError("Error decoding json")
    }
}

希望有开发者可以提供合理的实现方案,解决我这几天遇到的开发难题,在此提前致谢。
——Simon


实现方案

你现有的数据解析逻辑没有问题,只需要按导航层级拆分视图,通过NavigationLink串联各级页面即可实现四级钻取。如果是iOS 16及以上系统,推荐用NavigationStack替代已废弃的NavigationView,以下代码兼容两种写法:

  • 首先给Machine结构体补充Identifiable协议,简化列表遍历写法:
struct Machine: Decodable, Identifiable {
    // 本地唯一标识,不影响原有JSON解析逻辑
    let id = UUID()
    let make: String
    let model: String
    let code: Int
}
  • 按四级导航结构分别实现对应视图,代码如下:
import SwiftUI

// 第一级:应用首页(根入口)
struct ContentView: View {
    private let rootData = appliances.appliances
    
    var body: some View {
        NavigationView {
            List {
                NavigationLink {
                    // 跳转第二级:家电大类列表
                    ApplianceCategoryListView(categories: rootData)
                } label: {
                    Text("家电产品分类")
                }
            }
            .navigationTitle("首页")
        }
        // 适配iPad端导航显示样式
        .navigationViewStyle(.stack)
    }
}

// 第二级:家电大类列表
struct ApplianceCategoryListView: View {
    let categories: [Appliance]
    
    var body: some View {
        List(categories) { category in
            NavigationLink {
                // 跳转第三级:当前大类下的产品列表
                MachineListView(
                    machines: category.machines,
                    categoryName: category.title
                )
            } label: {
                Text(category.title)
            }
        }
        .navigationTitle("家电大类")
    }
}

// 第三级:产品列表
struct MachineListView: View {
    let machines: [Machine]
    let categoryName: String
    
    var body: some View {
        List(machines) { machine in
            NavigationLink {
                // 跳转第四级:产品详情页
                MachineDetailView(machine: machine)
            } label: {
                VStack(alignment: .leading, spacing: 4) {
                    Text(machine.model)
                        .font(.headline)
                    Text(machine.make)
                        .font(.subheadline)
                        .foregroundColor(.secondary)
                }
                .padding(.vertical, 4)
            }
        }
        .navigationTitle(categoryName)
    }
}

// 第四级:产品详情页
struct MachineDetailView: View {
    let machine: Machine
    
    var body: some View {
        Form {
            LabeledContent("品牌", value: machine.make)
            LabeledContent("型号", value: machine.model)
            LabeledContent("产品编码") {
                Text("\(machine.code)")
            }
        }
        .navigationTitle("产品详情")
        .navigationBarTitleDisplayMode(.inline)
    }
}

运行说明

  • 将ContentView设置为App入口的根视图即可正常运行
  • 确保本地JSON文件已加入项目Target的Copy Bundle Resources构建阶段,否则会触发文件找不到的崩溃
  • 如果后续需要扩展更多分类层级,直接复用「列表+NavigationLink跳转下一级」的结构即可,只要数据模型保持嵌套Decodable结构,不需要修改原有解析逻辑
  • 若要适配iOS 16+最新导航API,只需要把NavigationView替换为NavigationStack,移除.navigationViewStyle(.stack)修饰符,其余代码无需改动

内容的提问来源于stack exchange,提问作者OxfordSi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:18:36