Consider this piece of code
struct B {
var data: Int
}
struct A {
var data: Int
var b: B?
}
func test() {
var a = A(data: 1, b: B(data: 1))
a.b?.data = 3 // This works well
a[keyPath: \.b?.data] = 3 // Cannot assign through subscript: key path is read-only
let kp = \A?.?.data // Only way to get a KeyPath<Root, Int?>, cannot be Writable
}
My goal is to be able to create a WritableKeyPath
for something optional. Mostly, you can do something like this in a @Binding
in SwiftUI (as it's dynamic in nature), but you cannot do it in a KeyPath. Now, the obvious solution is to add a mandatory unwrap (!
), but this means less safeguarded code because Optionals cannot be used as writable reference.
This is obviously a simplified example, but my piece of code is about updating objects deep in an hierarchy that contains optionals - it resolves either to \Project.zones
(Zone
type) or \Project.zones[zoneIndex].asPageZone?.zones
(Zone?
type). I wanted to use WritableKeyPath
for this, so I have a generic way to update a zone anywhere in the project, including sub-zones, but it currently doesn't seem possible. So I changed my asPageZone?
to asPageZone!
, and this works well, but I try to have safe code, and I feel bad doing this.
Anything obvious I'm missing?
Otherwise, I'm proposing it should be possible to do an optional keyPath
write.
Also, it should be possible to create a wrapped optional version of a non-optional keyPath
without resorting to an optional Root
type (see kp
variable, as the only workaround I know).