How to support my own Property Wrapper(s) inside ObservableState? #3016
-
Apologies if this has already been announced during the observation or shared state beta, I've been going round in circles a bit trying to adopt observation with my TCA projects... I have a micro-library to support "loading" in TCA based applications. It has a custom property wrapper, The challenge I am facing, is how to make this play nicely with Looking at recent sources of the I can think of a couple of possible ways forward
Let's start with option 1, in theory this is totally possible, I've looked at the Indeed, what I want to achieve is the same as what any other developer would want to support their own custom property wrapper inside ObservableState. In general though - this solution does not scale very well, and it makes writing a custom property wrapper (or even macro) which plays nicely with For option 2, in many cases, I don't actually need to actively support observation - instead I just want to be ignored by the Keen to know what others think about this, or perhaps there is another solution out there. 😀 |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I had to tackle this problem - we also have a I solved this by introducing a separate property wrapper called The only catch is because Making private let _$perceptionRegistrar = Perception.PerceptionRegistrar()
internal nonisolated func access<Member>(
keyPath: KeyPath<Self, Member>,
file: StaticString = #file,
line: UInt = #line
) {
_$perceptionRegistrar.access(self, keyPath: keyPath, file: file, line: line)
}
internal nonisolated func withMutation<Member, MutationResult>(
keyPath: KeyPath<Self, Member>,
_ mutation: () throws -> MutationResult
) rethrows -> MutationResult {
try _$perceptionRegistrar.withMutation(of: self, keyPath: keyPath, mutation)
} Then add a stored property to store the internal state for your property wrapper and make public var wrappedValue: Value? {
get {
access(keyPath: \.state)
return state.currentValue
}
set {
withMutation(keyPath: \.state) {
state = .loaded(newValue)
}
}
} You can also do the same thing for |
Beta Was this translation helpful? Give feedback.
I had to tackle this problem - we also have a
@Loadable
property wrapper that does a very similar thing to yours.I solved this by introducing a separate property wrapper called
@ObservedLoadable
that supports observation - both property wrappers use the same underlyingLoadableState
type and supporting reducers/APIs, but the@ObservedLoadable
does its own observation tracking internally.The only catch is because
@ObservableState
does not know about this macro, you need to also explicitly mark the property as@ObservationStateIgnored
- it would be nice if the macro supported a way of declaring other macros to be ignored.Making
@ObservedLoadable
work was actually quite straightforward - …