SwiftUI中NavigationLinks优化及区域数据传递问题咨询
解决方案:统一导航逻辑+消除冗余视图
1. 先梳理数据关联逻辑
首先给Region结构体加一个标识字段,用来和对应区域的Shrine数组绑定:
struct Region: Identifiable { var id: String let regionName: String let regionImage: String let shrineAmount: Int let regionKey: String // 新增:用来匹配对应区域的Shrine数据,比如"akkala"、"centralHyrule" }
然后调整ShrineList,增加一个通过regionKey获取对应数据的方法:
struct ShrineList { static var akkala: [Shrine] = [ // Akkala区域的Shrine数据 ] static var centralHyrule: [Shrine] = [ // CentralHyrule区域的Shrine数据 ] // 根据regionKey返回对应区域的Shrine数组 static func getShrines(for key: String) -> [Shrine] { switch key { case "akkala": return akkala case "centralHyrule": return centralHyrule // 后续新增区域直接加case即可 default: return [] } } }
2. 写一个通用的Shrine列表视图
不用每个区域单独写视图,所有区域共用这一个:
struct ShrineListView: View { let shrineData: [Shrine] @EnvironmentObject var completed: Favorites var body: some View { List(shrineData) { shrine in // 这里写单个Shrine的单元格布局,示例如下 HStack { Image(shrine.imageName) .resizable() .frame(width: 50, height: 50) VStack(alignment: .leading) { Text(shrine.title) .font(.headline) Text(shrine.location) .font(.caption) } Spacer() Image(systemName: shrine.isCompleted ? "checkmark.circle.fill" : "circle") .foregroundColor(shrine.isCompleted ? .green : .gray) } } .navigationTitle("Shrines") } }
3. 重构Region列表单元格
把原来的单元格代码提取成单独视图,让主视图更简洁:
struct RegionListItemView: View { let region: Region var body: some View { ZStack { Image(region.regionImage) .resizable() .scaledToFill() .frame(width: 420, height: 100) Color.black .frame(width: 400, height: 100) .opacity(0.1) HStack(spacing: 2) { VStack(alignment: .leading, spacing: 1) { Text(region.regionName) .font(.system(size: 25, weight: .bold)) .lineLimit(1) .minimumScaleFactor(0.8) .foregroundColor(.white) .shadow(radius: 2) Text("\(region.shrineAmount) Shrines") .font(.system(size: 12, weight: .medium)) .foregroundColor(.white) } .padding(.leading, 40) Spacer() } } } }
4. 修改主视图的导航逻辑
现在可以动态绑定数据,不用硬编码每个区域的视图:
struct RegionViewOpt: View { @StateObject var completed = Favorites() @State private var regionlist: [Region] = RegionList.regions var body: some View { // iOS16+推荐用NavigationStack替代NavigationView NavigationStack { List(regionlist) { region in NavigationLink( destination: ShrineListView(shrineData: ShrineList.getShrines(for: region.regionKey)) ) { RegionListItemView(region: region) } .listRowSeparator(.hidden) } .navigationTitle("Regions") } .environmentObject(completed) } }
核心逻辑说明
- 通过
regionKey建立区域和Shrine数据的绑定,新增区域时只需要给Region加对应key、给ShrineList加对应数组和case即可 - 通用视图复用列表逻辑,彻底消除冗余代码
- 单元格抽离后,主视图结构更清晰,后续修改样式也更方便
内容的提问来源于stack exchange,提问作者Voxx3010
相关产品推荐
相关产品推荐

