@dan-zheng and I have a test case where we compare class keypaths that we create at runtime and an explicit array of hardcoded keypaths to class members.
class SomeClass {
var foo = 0
}
let classKeyPaths: [PartialKeyPath<SomeClass>] = createKeyPaths(for: SomeClass.self)
XCTAssertEqual(classKeyPaths, [\SomeClass.foo])
and we're hitting the assertion because the two are not equal. We create keypaths with components that are either struct
or class
depending on the type, but I found out that the Swift compiler emits computed keypaths for non-final class setters to be dynamically dispatched. Why is that? I tested that the keypaths we create using class
kind still appear to work reading/writing to the property of the class.
let someClass = SomeClass()
let fooKeyPath = someClassKeyPaths[0]
someClass[keyPath: fooKeyPath] = 10
print(someClass.foo) // 10
print(someClass[keyPath: fooKeyPath]) // 10
So I dug a little deeper and found that keypath equality also compared the component values which makes sense why we're hitting the assertion because our keypaths have a buffer size of 4, while compiler emitted ones have 32.
- Why this decision? Is there some Objective-C consideration here? Is our method supposed to work?
- Is there anyway to reconstruct a keypath with the identifier, getter, and setter at runtime? (I think the answer to this one is no.)
cc: @Joe_Groff