如何通过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
相关产品推荐
相关产品推荐

