Reputation: 2333
Consider the following snippet of code
class A {
var value: Int?
}
let a: A? = A()
let kp = \A.value
a?[keyPath: kp] = 10
print(a?.value)
This works perfectly and Optional(10)
is printed as expected. In my actual app the field I'm trying to set this way is declared as Date?
and it causes some strange errors. The MWE of my actual app is this:
class A {
var value: Date?
}
let a: A! = A()
let kp = \A.value
a?[keyPath: kp] = Date() // Line with error
print(a?.value)
However the compiler complains about the highlighted line and says:
Value of optional type 'Date?' must be unwrapped to a value of type 'Date'
Fix: Coalesce using '??' to provide a default when the optional value contains 'nil'
Fix: Force-unwrap using '!' to abort execution if the optional value contains 'nil'
Is this a bug of the compiler we can expect to be fixed before the final release or there's something I'm not understanding about key-paths?
I'm using Xcode 11 beta 3 but I've encountered the same problem also in beta 2. If it can be useful the actual code is here.
Upvotes: 7
Views: 1281
Reputation: 876
I bumped into similar problem:
import Foundation
struct Outer {
var inner: Inner
init() {
inner = Inner()
}
}
struct Inner {
var date: Date?
}
var outer = Outer()
outer[keyPath: \Outer.inner][keyPath: \Inner.date] = Date() // Line with error
print(outer.inner.date)
error: value of optional type 'Date?' must be unwrapped to a value of type 'Date'
outer[keyPath: \Outer.inner][keyPath: \Inner.date] = Date() // Line with error
^
note: coalesce using '??' to provide a default when the optional value contains 'nil'
outer[keyPath: \Outer.inner][keyPath: \Inner.date] = Date() // Line with error
^
?? <#default value#>
note: force-unwrap using '!' to abort execution if the optional value contains 'nil'
outer[keyPath: \Outer.inner][keyPath: \Inner.date] = Date() // Line with error
^
!
Strangely, casting the value to an optional works
outer[keyPath: \Outer.inner][keyPath: \Inner.date] = Date() as Date? // Works
Therefore, I believe a more general workaround to this problem is to explicitly cast the value to an optional as Date?
Upvotes: 1
Reputation: 51920
Writing this without ! and ? works
let a = A()
let kp = \A.value
a[keyPath: kp] = Date()
print(a.value)
or only as optional
let a: A? = A()
let kp = \A.value
a?[keyPath: kp] = Date()
print(a?.value)
Upvotes: 3