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
相关产品推荐
相关产品推荐

