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

Swift 5.7数组扩展KeyPath递归查找Identifiable元素失效问题

问题成因
  • 代码中e[keyPath: recursivePath] as [any Identifiable]的类型擦除操作,把原本强类型的具体元素数组转成了存在型(existential)数组[any Identifiable],此时数组元素类型是存在类型any Identifiable,而非原数组中遵循Identifiable协议的具体元素类型。
  • 自定义数组扩展的约束是Array where Element: Identifiable,要求数组元素是具体的、遵循Identifiable协议的类型,而存在类型any Identifiable本身是协议容器类型,不满足该泛型约束,因此无法匹配到自定义的递归下标,调用直接失败。
  • 原下标未指定第一个参数的外部标签,调用时容易和系统默认的整数索引下标混淆,可读性较差。

正确实现

不需要做任何类型擦除,直接利用Swift强类型特性递归即可:recursivePath指向的子数组本身就是[Element]类型,天然满足扩展的泛型约束,可以直接调用自定义下标完成递归查找,兼容Swift 5.7、Xcode 14.0 beta (14A5228q)环境。

extension Array where Element: Identifiable {
    subscript(id targetId: Element.ID?, recursivePath: KeyPath<Element, Array<Element>>) -> Element? {
        guard let targetId = targetId else {
            return nil
        }
        for element in self {
            // 当前层命中直接返回
            if element.id == targetId {
                return element
            }
            // 递归查找子节点,无需类型转换
            if let matched = element[keyPath: recursivePath][id: targetId, recursivePath: recursivePath] {
                return matched
            }
        }
        return nil
    }
}

使用示例

// 示例树节点
struct MenuItem: Identifiable {
    let id: String
    let name: String
    var subItems: [MenuItem]
}

// 构造测试树结构
let menuTree: [MenuItem] = [
    MenuItem(id: "home", name: "首页", subItems: []),
    MenuItem(id: "settings", name: "设置", subItems: [
        MenuItem(id: "account", name: "账号设置", subItems: [
            MenuItem(id: "avatar", name: "修改头像", subItems: []),
            MenuItem(id: "password", name: "修改密码", subItems: [])
        ]),
        MenuItem(id: "notification", name: "通知设置", subItems: [])
    ])
]

// 递归查找id为"avatar"的节点
let targetItem = menuTree[id: "avatar", recursivePath: \.subItems]
// 返回结果为name="修改头像"的MenuItem实例

实现说明:递归查找的时间复杂度为O(n),n为树结构的总节点数,无额外类型转换开销。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:36:14