-
Notifications
You must be signed in to change notification settings - Fork 78
Description
Description
It seems that a change to any binding derived from @Perception.Bindable will invalidate every binding that is derived from that same bindable.
Looking at the source for Bindable, it seems this is the reason:
public subscript<Subject>(
dynamicMember keyPath: ReferenceWritableKeyPath<Value, Subject>
) -> Binding<Subject> where Value: AnyObject {
withPerceptionTracking {
self.$observer[dynamicMember: (\Observer.object).appending(path: keyPath)]
} onChange: { [send = UncheckedSendable(self.observer.objectWillChange.send)] in
send.value()
}
}A withPerceptionTracking block is run for each keyPath that is subscripted, but the onChange is not scoped in any way, so any change will invalidate the entire Bindable.
This is a regression from 1.1.4 to 1.1.5 and all later versions.
Checklist
- I have determined that this bug is not reproducible using Swift's observation tools. If the bug is reproducible using the
@Observablemacro or another tool from theObservationframework, please file it directly with Apple. - If possible, I've reproduced the issue using the
mainbranch of this package. - This issue hasn't been addressed in an existing GitHub issue or discussion.
Expected behavior
Changes to a single binding derived from a bindable only invalidate observations of that binding.
Actual behavior
Changes to a single binding invalidate every binding derived from that bindable.
Steps to reproduce
Run this view from the example app:
@Perceptible
class DemoModel {
var toggle1 = false
var toggle2 = false
}
struct DemoView: View {
@Perception.Bindable
var model: DemoModel
var body: some View {
WithPerceptionTracking {
VStack {
ToggleView(name: "1", isOn: $model.toggle1)
ToggleView(name: "2", isOn: $model.toggle2)
}
}
}
}
struct ToggleView: View {
var name: String
@Binding var isOn: Bool
var body: some View {
let _ = print("evaluated ToggleView \(name)")
Toggle("isOn", isOn: $isOn)
}
}When run with Perception 1.1.4 or Apple Observation, changing a toggle causes a single log for the ToggleView that is invalidated.
Under Perception 1.1.5 and later, changing a toggle emits logs for both ToggleViews.
Perception version information
1.6.0
Destination operating system
iOS 16.4
Xcode version information
Version 16.1 (16B40)
Swift Compiler version information
swift-driver version: 1.115 Apple Swift version 6.0.2 (swiftlang-6.0.2.1.2 clang-1600.0.26.4)
Target: arm64-apple-macosx15.0