在 Swift 4 中访问 PartialKeyPath 的可选值
Accessing the optional value of a PartialKeyPath in Swift 4
使用 PartialKeyPath
API,如何访问关键路径引用的值?例如,这适用于非可选值,但不适用于 Optional
值。
我遇到的问题是 self[keyPath: keyPath]
returns 一个非可选的 Any
值。
struct Element {
let name: String
let mass: Double?
func stringValue(_ keyPath: PartialKeyPath<Element>) -> String {
let value = self[keyPath: keyPath]
switch value {
case let string as String:
return string.capitalized
case nil:
return "N/A"
case let value:
return String(describing: value)
}
}
}
let element = Element(name: "Helium", mass: 4.002602)
let string = element.stringValue(\Element.mass) /* Optional(4.002602) */
结果是 case nil
从未执行,最后一个案例被打印为 Optional(value)
。
如何正确解包 value
以提取可选内容?
解决方案是使用 Mirror
解包可选,这似乎不是最佳选择。期待 Swift!
中更好的反射支持
func unwrap(_ value: Any) -> Any? {
let mirror = Mirror(reflecting: value)
if mirror.displayStyle != .optional {
return value
}
if let child = mirror.children.first {
return child.value
} else {
return nil
}
}
struct Element {
let name: String
let mass: Double?
func stringValue(_ keyPath: PartialKeyPath<AtomicElement>) -> String {
guard let value = unwrap(self[keyPath: keyPath]) else {
return "N/A"
}
switch value {
case let string as String:
return string.capitalized
default:
return String(describing: value)
}
}
}
let element = Element(name: "Helium", mass: 4.002602)
let string = element.stringValue(\Element.mass) /* 4.002602 */
使用 PartialKeyPath
API,如何访问关键路径引用的值?例如,这适用于非可选值,但不适用于 Optional
值。
我遇到的问题是 self[keyPath: keyPath]
returns 一个非可选的 Any
值。
struct Element {
let name: String
let mass: Double?
func stringValue(_ keyPath: PartialKeyPath<Element>) -> String {
let value = self[keyPath: keyPath]
switch value {
case let string as String:
return string.capitalized
case nil:
return "N/A"
case let value:
return String(describing: value)
}
}
}
let element = Element(name: "Helium", mass: 4.002602)
let string = element.stringValue(\Element.mass) /* Optional(4.002602) */
结果是 case nil
从未执行,最后一个案例被打印为 Optional(value)
。
如何正确解包 value
以提取可选内容?
解决方案是使用 Mirror
解包可选,这似乎不是最佳选择。期待 Swift!
func unwrap(_ value: Any) -> Any? {
let mirror = Mirror(reflecting: value)
if mirror.displayStyle != .optional {
return value
}
if let child = mirror.children.first {
return child.value
} else {
return nil
}
}
struct Element {
let name: String
let mass: Double?
func stringValue(_ keyPath: PartialKeyPath<AtomicElement>) -> String {
guard let value = unwrap(self[keyPath: keyPath]) else {
return "N/A"
}
switch value {
case let string as String:
return string.capitalized
default:
return String(describing: value)
}
}
}
let element = Element(name: "Helium", mass: 4.002602)
let string = element.stringValue(\Element.mass) /* 4.002602 */