SwiftUI中导航目标为何仅绑定数组最后一个联系人数据?
问题原因与解决方案
你遇到的问题核心在于所有ContactCell共用了同一个shouldPresentContactMainView状态变量,并且navigationDestination的触发逻辑依赖这个全局状态。当你点击任意单元格时,只是把这个共享状态改成true,此时SwiftUI会取循环结束后最后一次迭代的$contact值来渲染ContactMainView,所以不管点哪个单元格,最终都会显示数组最后一个联系人的数据。
方案一:使用navigationDestination(item:)替代isPresented(推荐)
这是SwiftUI处理列表/网格跳转的标准写法,通过绑定可选对象精准控制跳转目标:
- 先定义一个可选的联系人状态变量:
@State private var selectedContact: Contact? // 替换成你的联系人实际类型
- 修改ForEach和跳转逻辑:
ForEach(contacts, id: \.self) { contact in ContactCell(contact: contact) .onTapGesture { selectedContact = contact } .navigationDestination(item: $selectedContact) { selected in ContactMainView(contact: selected) } }
这里不需要绑定$contacts,点击时直接把选中的联系人赋值给selectedContact,navigationDestination会自动识别对象变化,渲染对应的详情页。
方案二:为每个单元格单独绑定状态(不推荐)
如果一定要用isPresented的方式,需要给每个联系人创建独立的状态变量,但这种方式在数组元素较多时会浪费资源,仅作参考:
- 假设你的联系人模型有唯一标识(比如
id),用字典存储每个联系人的跳转状态:
@State private var presentationStates: [String: Bool] = [:] // 这里的String对应Contact的id类型
- 修改循环逻辑:
ForEach($contacts, id: \.id) { $contact in ContactCell(contact: contact) .navigationDestination(isPresented: $presentationStates[contact.id, default: false]) { ContactMainView(contact: $contact) } .onTapGesture { // 先重置所有状态,再设置当前联系人的状态为true presentationStates.keys.forEach { presentationStates[$0] = false } presentationStates[contact.id] = true } }
这种方式需要维护每个联系人的独立状态,逻辑复杂且效率低,远不如方案一简洁实用。
内容的提问来源于stack exchange,提问作者user14023669
相关产品推荐
相关产品推荐

