import CasePaths
extension CasePathable where AllCasePaths: CasePathReflectable<Self> {
func associatedValue<T: CasePathable>() -> T? where T.AllCasePaths: CasePathReflectable<T> {
let caseKeyPath = Self.allCasePaths[self]
return self[case: caseKeyPath] as? T
}
}
注意:严格来说,我在这里使用的PointFree 的 swift-case-paths库不需要熟悉。从根本上讲,我的问题仅与 Swift 本身有关。
因此,给定上述正确的函数,目标是递归应用它,以检索最深的嵌套值。
但是如何处理这里的类型?因为每个关联值可能是不同的类型。问题是该associatedValue()
函数返回一个T
必须指定的泛型。但对于通用解决方案,我们无法T
提前知道每一个。
我将给出一些具体的例子来提供更多背景信息:
@CasePathable
enum A {
case a(B)
case smthA
}
@CasePathable
enum B {
case b(C)
case smthB
}
@CasePathable
enum C {
case c
case smthC
}
let aValue: A = .a(.b(.c))
let bAssValue: B = aValue.associatedValue()! // .b(.c))
let cAssValue: C = bAssValue.associatedValue()! // .c
我将假设每个枚举案例最多有 1 个关联值。
由于您不知道中间类型,因此您需要使用存在类型。
any CasePathable
无法捕获的约束where AllCasePaths: CasePathReflectable<Self>
,因此需要引入额外的协议来表示这种类型。所有枚举都应符合
ReflectableCasePathable
。您还需要一个
associatedValue
返回的版本any ReflectableCasePathable
。注意,这
associatedValue
不需要依赖于AllCasePaths: CasePathReflectable<Self>
约束。它可以依赖于CasePathIterable
协议,您可以通过迭代找到正确的案例路径。那么您不必引入新的协议,但我离题了。
无论如何,您只需循环调用它即可。
还可以考虑这种替代设计,它允许您在“最底层”提取非枚举关联值。
这使你可以做这样的事情: