SwiftUI中如何获取可展开List被点击项的层级索引路径
SwiftUI 多层级展开List获取点击项完整索引路径实现方案
核心思路
List(children:) 初始化方法不会在渲染闭包里自动传递当前项的层级索引,我们可以通过ID匹配+递归遍历的方式,从根菜单数组逐层查找目标项,累积记录每一层的索引,最终得到完整的层级路径。
具体实现步骤
1. 补全根菜单定义
你代码中引用的sampleMenuItems是顶层根数组,补全定义如下(和你现有的三级菜单结构匹配):
// 顶层根菜单数组 let sampleMenuItems = [ MenuItem(name: "咖啡机", image: "espresso-machine", subMenuItems: espressoMachineMenuItems), MenuItem(name: "磨豆机", image: "grinder", subMenuItems: grinderMenuItems), MenuItem(name: "其他设备", image: "other", subMenuItems: otherMenuItems) ]
2. 实现递归索引路径查找方法
写一个通用递归方法,从根数组开始遍历,匹配菜单项的唯一id,逐层累积索引:
/// 递归查找目标菜单项的完整层级索引路径 /// - Parameters: /// - menuItems: 当前遍历的菜单数组 /// - targetID: 目标菜单项的唯一ID /// - currentPath: 递归过程中累积的路径,默认传空数组即可 /// - Returns: 完整索引路径数组(元素顺序对应从根到叶的每层索引),未找到返回nil func findIndexPath(in menuItems: [MenuItem], targetID: UUID, currentPath: [Int] = []) -> [Int]? { for (index, item) in menuItems.enumerated() { let updatedPath = currentPath + [index] // 匹配到目标项直接返回路径 if item.id == targetID { return updatedPath } // 存在子菜单则递归向下查找 if let subMenu = item.subMenuItems, let targetPath = findIndexPath(in: subMenu, targetID: targetID, currentPath: updatedPath) { return targetPath } } return nil }
3. 修改点击回调获取路径
在原有onTapGesture回调中,传入当前点击项的id调用查找方法,即可拿到完整路径:
.onTapGesture { guard let indexPath = findIndexPath(in: sampleMenuItems, targetID: item.id) else { return } // 打印基础信息 print("选中项名称:\(item.name)") print("索引路径数组:\(indexPath)") // 例:Leva S 对应输出 [0,0,1] // 拼接为你举例的代码访问路径格式 var accessPath = "sampleMenuItems[\(indexPath[0])]" for idx in 1..<indexPath.count { accessPath += ".subMenuItems![\(indexPath[idx])]" } print("代码访问路径:\(accessPath)") // 例:Leva S 对应输出 sampleMenuItems[0].subMenuItems![0].subMenuItems![1] // 可直接通过索引路径从根数组取到目标项 // var matchedItem = sampleMenuItems[indexPath[0]] // for idx in 1..<indexPath.count { // matchedItem = matchedItem.subMenuItems![indexPath[idx]] // } }
说明
- 该方案支持任意层级的菜单嵌套,不局限于2-3级结构
- 基于
MenuItem的唯一UUID做匹配,即使不同层级存在同名菜单项也不会匹配错误 - 拿到的
indexPath数组可以直接和List的展开/选中逻辑绑定使用
内容的提问来源于stack exchange,提问作者pzs7602
相关产品推荐
相关产品推荐

