Skip to content

Commit c57319e

Browse files
fl034claude
andcommitted
Fix initial value clobbered by resting leading tick
updateCentered wrote the centered tick back to the binding on first layout — before the deferred scrollTo(value) ran — so the strip's resting leading tick (range.lowerBound) overwrote the incoming value, then the scroll targeted the clobbered value. A picker created with value 13 would snap to 1. Gate write-backs on a new didCenter flag that flips true only after the initial scrollTo; split the one-time onAppear guard into didAppear. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent eda34de commit c57319e

1 file changed

Lines changed: 11 additions & 3 deletions

File tree

Sources/RulerPicker/RulerPicker.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ public struct RulerPicker: View {
6363
/// whose midX is closest to this is the selection.
6464
@State private var centerX: CGFloat = 0
6565
/// Set once after first layout so the initial `scrollTo` only runs once.
66+
@State private var didAppear = false
67+
/// True once the initial `scrollTo(value)` has run; write-backs to `value`
68+
/// are ignored before this so the resting leading tick can't clobber the
69+
/// incoming value.
6670
@State private var didCenter = false
6771
/// True while the selection is actively changing; drives the white flash.
6872
/// Resets shortly after scrolling settles so the tick fades back to tint.
@@ -148,12 +152,16 @@ public struct RulerPicker: View {
148152
.compositingGroup()
149153
.mask { edgeMask }
150154
.onAppear {
151-
guard !didCenter else { return }
152-
didCenter = true
155+
guard !didAppear else { return }
156+
didAppear = true
153157
// Defer until the content has laid out, otherwise the initial
154158
// scroll is dropped.
155159
Task {
156160
proxy.scrollTo(value, anchor: .center)
161+
// Only accept selection write-backs after we've centered on
162+
// the incoming value; otherwise the resting leading tick
163+
// clobbers `value` before this scroll runs.
164+
didCenter = true
157165
}
158166
}
159167
}
@@ -220,7 +228,7 @@ public struct RulerPicker: View {
220228
}
221229

222230
private func updateCentered(from centers: [Int: CGFloat]) {
223-
guard centerX > 0 else { return }
231+
guard centerX > 0, didCenter else { return }
224232
guard let key = Self.nearestTick(centers: centers, to: centerX), key != centered else { return }
225233
centered = key
226234
if value != key { value = key }

0 commit comments

Comments
 (0)