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

Swift中类未定义时,如何创建可写入键路径数组?

这问题我之前也碰到过,核心问题出在你对AnyClass的理解和KeyPath类型匹配上,咱们一步步拆解解决:

首先先解释报错原因:
你写的WritableKeyPath<AnyClass, Double>里的AnyClass其实是类的元类型(比如Class1.self的类型),而你要操作的是类的实例属性(比如Class1实例的tag),这两者完全不是一回事。编译器自然会报错,因为元类型本身根本没有tag或者volume这些实例属性。

而且退一步说,就算你改成AnyObject(任意对象实例的类型),WritableKeyPath<AnyObject, Double>也没法直接容纳\Class1.tag这种具体类的KeyPath——Swift是强类型语言,AnyObject不保证有tag属性,所以这种类型转换是不被允许的。

接下来给两种可行的解决方案,根据你的场景选:

方案一:用协议统一类型(类型安全首选)

如果你的Class1、Class2都是你能修改的类,最稳妥的方式是定义一个协议,把需要编辑的Double属性都声明进去,然后让这些类遵循协议:

// 定义协议,声明需要可写的Double属性
protocol DoublePropertyEditable {
    var tag: Double { get set }
    var volume: Double { get set }
}

// 让你的类遵循协议
class Class1: DoublePropertyEditable {
    var tag: Double = 0.0
    // 其他原有属性和方法...
}

class Class2: DoublePropertyEditable {
    var volume: Double = 0.0
    // 其他原有属性和方法...
}

然后你就可以用协议类型的KeyPath数组了,所有遵循协议的类都能兼容:

// 现在数组里的KeyPath都是针对协议类型的
var properties: [WritableKeyPath<DoublePropertyEditable, Double>] = [
    \.tag,
    \.volume
]

// 设置方法也改成接收协议类型的实例
func setProperty(keyIndex: Int, value: Double, on object: DoublePropertyEditable) {
    guard keyIndex < properties.count else { return } // 做个越界检查更安全
    object[keyPath: properties[keyIndex]] = value
}

调用示例:

let obj1 = Class1()
setProperty(keyIndex: 0, value: 15.0, on: obj1)
print(obj1.tag) // 输出 15.0

let obj2 = Class2()
setProperty(keyIndex: 1, value: 6.0, on: obj2)
print(obj2.volume) // 输出 6.0

这个方案的好处是完全类型安全,编译器会帮你检查所有遵循协议的类都实现了要求的属性,不会有运行时类型错误。

方案二:用闭包封装设置逻辑(无需修改原有类)

如果你的Class1、Class2是第三方库的类,没法修改它们来遵循协议,那可以用闭包来封装“设置值”的逻辑,把不同类的类型转换隐藏在闭包里:

// 数组里存的是闭包,每个闭包负责给对应类型的对象设置值
var propertySetters: [(AnyObject, Double) -> Void] = []

// 添加Class1的tag设置逻辑
propertySetters.append { obj, value in
    guard let class1Obj = obj as? Class1 else { return }
    class1Obj.tag = value
}

// 添加Class2的volume设置逻辑
propertySetters.append { obj, value in
    guard let class2Obj = obj as? Class2 else { return }
    class2Obj.volume = value
}

// 设置方法接收任意对象实例
func setProperty(keyIndex: Int, value: Double, on object: AnyObject) {
    guard keyIndex < propertySetters.count else { return }
    propertySetters[keyIndex](object, value)
}

调用示例:

let obj1 = Class1()
setProperty(keyIndex: 0, value: 25.0, on: obj1)
print(obj1.tag) // 输出 25.0

let obj2 = Class2()
setProperty(keyIndex: 1, value: 8.5, on: obj2)
print(obj2.volume) // 输出 8.5

这个方案更灵活,但需要手动处理类型转换,如果传入的对象类型不对,闭包会直接忽略设置操作,适合无法修改原有类的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:00:13