I’m trying to figure out how DynamicViewProperty in SwiftUI works, that mechanism is something I want as well :-> Does that use a custom reflection to make it work?
struct MyOwnCoolViewProperty : DynamicViewProperty {
var gotCalled = 0
mutating func update() { gotCalled += 1 }
}
struct MyView: View {
var prop = MyOwnCoolViewProperty()
var body ....
}
This is calling update before the body property is accessed. But how? 🙂
It is easy enough to get the dynamic properties using something like:
let dynamicProps = Mirror(reflecting: view).children.compactMap {
$0.value as? DynamicViewProperty
}
But that doesn't allow you to call a mutating function. Are they using custom reflection to achieve that, or doesn't this involve reflection at all?
On a high level it seems to be using much more than reflection, its actually directly calling into Swift runtime. Logic for this is implemented in private AttributeGraph framework written in C++, that weakly imports a lot of Swift runtime symbols.
This has interesting side effects, you can make the property ‘let’ and it will still be updated
I’ve looked at it briefly, so maybe someone will be able to provide more details.
To make the View's value "mutable" one just casts the pointer to a mutable one. Which explains why this works even if the properties are defined as let. Not sure whether that is really sound (optimiser might layout the properties differently?), but I guess the layout should be stable as part of the "ABI".