【发布时间】:2019-07-12 10:03:57
【问题描述】:
CaseIterable 协议允许您遍历枚举的情况,我想这样做,但对于静态属性,并获取它的值。你将如何实现理论上的PropertyIterable 协议?
我尝试过使用反射 (Mirror(reflecting:)),它适用于结构,但不适用于枚举
例如:
protocol PropertyIterable {
var allProperties: [String: T] { get } //will get you [String: Any/T]
}
仅供参考:可能计算属性 allProprties 未正确定义。但只是为了说明目的
enum Test: PropertyIterable {
static let foo = "blah"
static let bar = "blah2"
}
let test = Test.allProperties //will return ["foo": "blah", bar: "blah2"]
目前,当我打印 Mirror(describing: Test.self).children 时,我得到了这个:
AnyCollection<(label: Optional<String>, value: Any)>(_box: Swift._RandomAccessCollectionBox<Swift.LazyMapCollection<Swift.Range<Swift.Int>, (label: Swift.Optional<Swift.String>, value: Any)>>)
【问题讨论】:
-
您看到的那种类型是一种惰性类型,它包装了
Test的值。由于大多数人只想迭代这些值,因此将它们复制到一个新的数组中是没有意义的。如果您需要,您可以使用Array(Mirror(describing: Test.self).children)自己完成。但是随后,您会发现镜像不适用于这些自定义属性:( -
@Alexander 我试过
Array(Mirror(describing: Test.self).children),但我得到了一个空数组。那么,没有办法获取枚举中所有已定义属性的值吗?我想使用枚举来存储和组织常量。我从机器人娜塔莎那里得到了这个想法:natashatherobot.com/swift-enum-no-cases -
不,没有自动化的方法。充其量,您可以创建一个计算属性,该属性返回一个已手动列出的值的字典。
-
你知道是否有提议实施类似的东西吗?或者为什么值得像
CaseIterable那样获得案例而不是属性? -
编译器已经将此元数据烘焙到它构建的可执行文件中。调试器工具利用了这个元数据,但是没有 API(除了几乎没用的 Mirror)来访问它。他们还没有实施,因为它仍在经历很多变化。不过,这并没有阻止第三方对其进行逆向工程和实施反射库。请注意,随着这些实现细节在未来的 Swift 版本中发生变化,它们很容易被破坏。
标签: swift enums introspection swift-protocols