Is there any way to reference self
with Swift 4's new KeyPath
s?
Something like this works fine, we can address a property of an object:
func report(array: [Any], keyPath: AnyKeyPath) {
print(array.map({ $0[keyPath: keyPath] }))
}
struct Wrapper {
let name: String
}
let wrappers = [Wrapper(name: "one"), Wrapper(name: "two")]
report(array: wrappers, keyPath: \Wrapper.name)
But addressing an object itself seems impossible to me:
let strings = ["string-one", "string-two"]
report(array: strings, keyPath: \String.self) // would not compile
I suppose there should be some obvious way for this?
EDIT:
Or simply:
let s = "text-value"
print(s[keyPath: \String.description]) // works fine
print(s[keyPath: \String.self]) // does not compile
Unfortunately, this isn't something Swift keypaths currently support. However, I do think this is something they should support (with the exact syntax you're attempting to use, e.g \String.self
). All expressions have an implicit .self
member that just evaluates to the expression, so it seems like a perfectly natural extension to allow .self
in keypaths (Edit: This is now something that's being pitched).
Until supported (if at all), you can hack it with a protocol extension that adds a computed property that just forwards to self
:
protocol KeyPathSelfProtocol {}
extension KeyPathSelfProtocol {
var keyPathSelf: Self {
get { return self }
set { self = newValue }
}
}
extension String : KeyPathSelfProtocol {}
let s = "text-value"
print(s[keyPath: \String.description])
print(s[keyPath: \String.keyPathSelf])
You just need to conform types that you want to use "self keypaths" with to KeyPathSelfProtocol
.