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

SwiftUI中添加列表新项时如何在导航视图中推送编辑视图?

解决SwiftUI中点击添加按钮编程式导航到EditView的问题

针对你的需求,不需要依赖iOS17测试版的navigationDestination(item:destination:),可以根据不同iOS版本用以下方案实现:

iOS 16及以下(使用NavigationView)

通过隐藏的NavigationLink结合状态变量控制导航触发,点击添加按钮时切换状态即可跳转:

struct ContentView: View {
    @State private var items: [String] = ["Item 1", "Item 2"]
    @State private var isAddingNewItem = false
    
    var body: some View {
        NavigationView {
            List(items, id: \.self) { item in
                NavigationLink(item, destination: EditView(item: $items[items.firstIndex(of: item)!]))
            }
            .toolbar {
                Button("Add") {
                    isAddingNewItem = true
                }
            }
            // 隐藏的导航触发链接,放在背景不影响界面
            .background(
                NavigationLink(
                    destination: EditView(newItem: { newItem in
                        items.append(newItem)
                        isAddingNewItem = false // 跳转完成后重置状态
                    }),
                    isActive: $isAddingNewItem
                ) {
                    EmptyView()
                }
            )
        }
    }
}

// 通用EditView,支持编辑已有项或添加新项
struct EditView: View {
    @Binding private var item: String?
    private let newItemCallback: ((String) -> Void)?
    
    // 添加新项的初始化器
    init(newItem: @escaping (String) -> Void) {
        self._item = .constant(nil)
        self.newItemCallback = newItem
    }
    
    // 编辑已有项的初始化器
    init(item: Binding<String>) {
        self._item = item
        self.newItemCallback = nil
    }
    
    @State private var inputText = ""
    
    var body: some View {
        Form {
            TextField("输入内容", text: $inputText)
        }
        .navigationTitle(item == nil ? "添加新项" : "编辑项")
        .toolbar {
            Button("保存") {
                if let callback = newItemCallback {
                    callback(inputText)
                } else if var currentItem = item {
                    currentItem = inputText
                }
            }
        }
        .onAppear {
            inputText = item ?? ""
        }
    }
}

iOS 16+(使用NavigationStack)

利用NavigationStack的path绑定来管理导航栈,通过自定义枚举标记导航目标:

struct ContentView: View {
    @State private var items: [String] = ["Item 1", "Item 2"]
    @State private var navigationPath = NavigationPath()
    
    // 定义导航目标枚举,必须遵循Hashable
    enum NavDestination: Hashable {
        case editItem(String)
        case addNewItem
    }
    
    var body: some View {
        NavigationStack(path: $navigationPath) {
            List(items, id: \.self) { item in
                NavigationLink(item, value: NavDestination.editItem(item))
            }
            .toolbar {
                Button("Add") {
                    navigationPath.append(NavDestination.addNewItem)
                }
            }
            // 绑定导航目标对应的视图
            .navigationDestination(for: NavDestination.self) { destination in
                switch destination {
                case .editItem(let item):
                    if let index = items.firstIndex(of: item) {
                        EditView(item: $items[index])
                    }
                case .addNewItem:
                    EditView(newItem: { newItem in
                        items.append(newItem)
                        navigationPath.removeLast() // 保存后返回列表
                    })
                }
            }
        }
    }
}

// EditView实现同上,无需修改

多版本兼容写法

如果需要同时支持iOS15及以下和iOS16+,可以用#available做版本区分:

struct ContentView: View {
    @State private var items: [String] = ["Item 1", "Item 2"]
    @State private var isAddingNewItem = false
    @State private var navigationPath = NavigationPath()
    
    enum NavDestination: Hashable {
        case editItem(String)
        case addNewItem
    }
    
    var body: some View {
        if #available(iOS 16.0, *) {
            NavigationStack(path: $navigationPath) {
                listContent
                    .toolbar { addButton }
                    .navigationDestination(for: NavDestination.self) { destination in
                        destinationView(for: destination)
                    }
            }
        } else {
            NavigationView {
                listContent
                    .toolbar { addButton }
                    .background(hiddenAddLink)
            }
        }
    }
    
    // 复用列表内容
    private var listContent: some View {
        List(items, id: \.self) { item in
            if #available(iOS 16.0, *) {
                NavigationLink(item, value: NavDestination.editItem(item))
            } else {
                NavigationLink(item, destination: EditView(item: $items[items.firstIndex(of: item)!]))
            }
        }
    }
    
    // 复用添加按钮
    private var addButton: some View {
        Button("Add") {
            if #available(iOS 16.0, *) {
                navigationPath.append(NavDestination.addNewItem)
            } else {
                isAddingNewItem = true
            }
        }
    }
    
    // iOS15及以下的隐藏导航链接
    private var hiddenAddLink: some View {
        NavigationLink(
            destination: EditView(newItem: { newItem in
                items.append(newItem)
                isAddingNewItem = false
            }),
            isActive: $isAddingNewItem
        ) {
            EmptyView()
        }
    }
    
    // iOS16+的导航目标视图
    @ViewBuilder
    private func destinationView(for destination: NavDestination) -> some View {
        switch destination {
        case .editItem(let item):
            if let index = items.firstIndex(of: item) {
                EditView(item: $items[index])
            }
        case .addNewItem:
            EditView(newItem: { newItem in
                items.append(newItem)
                navigationPath.removeLast()
            })
        }
    }
}

以上方案都能实现点击添加按钮后,以导航详情视图打开EditView,完成新项编辑后加入列表的需求,且不依赖iOS17的测试版API。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 09:28:16