SwiftUI中如何编辑ForEach内NavigationLink标签中的数组元素属性
解决方案
一、点击TextField触发跳转的修复
该问题的核心是NavigationLink默认会捕获其label范围内所有点击事件,非List容器下苹果未做点击区域的特殊区分,按如下方式修改即可:
- 改用编程式导航,仅在非编辑状态下点击卡片主体才触发跳转
- 对编辑按钮、TextField添加独立点击响应,阻断NavigationLink的点击捕获
二、TextField显示时自动全选内容的实现
通过@FocusState控制TextField聚焦状态,配合UITextField的原生选中文本能力实现自动全选。
完整修改后代码
1. ContentView 修改
struct ContentView: View { @EnvironmentObject var allPlaces: ViewModel // 存储当前选中要跳转的Collection,iOS16+适用,低版本可改用isActive绑定 @State var selectedCollection: Collection? var body: some View { NavigationView { // 替换为你需要的ScrollView+LazyVGrid即可 ScrollView { LazyVStack { ForEach($allPlaces.displayedCollectionsArray) { $collection in VStack { CollectionCardView(collection: $collection, isHidden: false) // 仅非编辑状态下点击才触发跳转 .onTapGesture { selectedCollection = collection } } } } } .navigationDestination(item: $selectedCollection) { collection in Text("Detail View of \(collection.name)") } .navigationBarHidden(true) } } }
2. CollectionCardView 修改
struct CollectionCardView: View { @Binding var collection: Collection @State var isHidden: Bool = false let testkey = "hello" // 控制TextField聚焦 @FocusState var isFocused: Bool var body: some View { VStack (alignment: .leading) { HStack { ZStack (alignment: .leading) { Text(collection.name) .foregroundColor(Color.black) .opacity(isHidden ? 0 : 1) .frame(width: 200, height: 40, alignment: .leading) if collection.name != "Travel gems" { TextField(testkey, text: $collection.name) .foregroundColor(Color.black) .textFieldStyle(RoundedBorderTextFieldStyle()) .frame(width: 200, height: 40, alignment: .leading) .opacity(isHidden ? 1 : 0) .focused($isFocused) // 阻断NavigationLink的点击捕获 .onTapGesture {} // 聚焦时自动全选文本 .onChange(of: isFocused) { newValue in if newValue { DispatchQueue.main.async { UIApplication.shared.sendAction(#selector(UIResponder.selectAll(_:)), to: nil, from: nil, for: nil) } } } } } if collection.name != "Travel gems" { Image(systemName: "square.and.pencil") .foregroundColor(Color.gray) .onTapGesture { isHidden.toggle() isFocused = isHidden } } } .padding(.leading, 24) .padding(.trailing, 24) } .padding(.top, 10) .padding(.bottom, 10) } }
额外说明
- 原有代码中将
collecName作为局部@State的写法无法同步修改到环境对象的数组中,这里改为直接绑定数组元素的name属性,修改后会自动同步到ViewModel - 如果需要兼容iOS15及以下版本,把
navigationDestination替换为带isActive绑定的隐形NavigationLink即可 - 替换外层容器为
LazyVGrid即可满足你生产环境的布局需求,导航逻辑不需要修改
内容的提问来源于stack exchange,提问作者christianzags
相关产品推荐
相关产品推荐

