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

iOS 16 SwiftUI Navigation Stack:能否移除Company的index实现循环跳转

移除Company的index字段,基于Navigation Stack实现循环跳转优化方案

优化思路

完全可以移除Company结构体中的index字段,通过数组索引匹配+取模运算实现循环跳转,核心是利用Company已实现的Hashable协议定位当前元素在数组中的位置,再直接修改NavigationStack的path属性完成页面切换。

步骤1:精简Company结构体

删除冗余的index字段,保留必要的标识与数据字段:

struct Company: Identifiable, Hashable {
    var id = UUID()
    let name: String
    let address: String
}

步骤2:更新数据源初始化

去掉初始化时的index参数:

let companies: [Company] = [
    .init(name: "Apple", address: "Infinity Loop"),
    .init(name: "Facebook", address: "Hacker Way"),
    .init(name: "Google", address: "Mountain View")
]

步骤3:重构详情页跳转逻辑

删除无用的@State var index: Int = 0,在「Go Next」按钮的点击事件中,通过数组索引定位+取模运算实现循环:

Button {
    // 找到当前公司在数组中的位置
    guard let currentIndex = companies.firstIndex(of: company) else { return }
    // 取模运算实现循环切换
    let nextIndex = (currentIndex + 1) % companies.count
    // 更新导航栈路径,跳转到下一个公司页面
    path = [companies[nextIndex]]
} label: {
    Text("Go Next")
}

如果需要显示当前元素的序号,同样通过firstIndex(of:)获取:

if let currentIndex = companies.firstIndex(of: company) {
    Text("\(currentIndex)")
} else {
    Text("0")
}

完整优化后代码

import SwiftUI

struct Company: Identifiable, Hashable {
    var id = UUID()
    let name: String
    let address: String
}

struct ContentView: View {
    let companies: [Company] = [
        .init(name: "Apple", address: "Infinity Loop"),
        .init(name: "Facebook", address: "Hacker Way"),
        .init(name: "Google", address: "Mountain View")
    ]
    
    @State var path: [Company] = []
    
    var body: some View {
        VStack {
            NavigationStack(path: $path) {
                List(companies, id: \.self) { company in
                    NavigationLink(company.name, value: company)
                }
                .navigationDestination(for: Company.self) { company in
                    VStack {
                        // 显示当前元素序号
                        if let currentIndex = companies.firstIndex(of: company) {
                            Text("\(currentIndex)")
                        } else {
                            Text("0")
                        }
                        Text(company.address)
                        
                        Button {
                            guard let currentIndex = companies.firstIndex(of: company) else { return }
                            let nextIndex = (currentIndex + 1) % companies.count
                            path = [companies[nextIndex]]
                        } label: {
                            Text("Go Next")
                        }
                        
                        Button {
                            path.removeAll()
                        } label: {
                            Text("Go Home")
                        }
                    }
                }
            }
        }
        .padding()
    }
}

关键说明

  1. Hashable协议的作用:因为Company实现了Hashable,firstIndex(of:)可以精准匹配当前元素在数组中的位置,无需依赖自定义index字段。
  2. 取模运算实现循环:(currentIndex + 1) % companies.count确保索引走到最后一个元素时,加1后取模会回到0,完美实现循环切换。
  3. 直接操作path:通过修改path数组为下一个Company实例,NavigationStack会自动处理页面跳转与栈更新,符合iOS 16导航栈的设计逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 16:15:40