Skip to content

Instantly share code, notes, and snippets.

@bryan1anderson
Created August 8, 2025 18:11
Show Gist options
  • Select an option

  • Save bryan1anderson/390ab1fd43d2a028dec22f8fa66c169e to your computer and use it in GitHub Desktop.

Select an option

Save bryan1anderson/390ab1fd43d2a028dec22f8fa66c169e to your computer and use it in GitHub Desktop.
SwiftUI ScrollView ScrollPosition Anchor is broken
import SwiftUI
/**
This view demonstrates that scroll anchors are IGNORED when using `.scrollPosition(...).scrollTo(id:anchor:)`.
- Using `.scrollViewProxy.scrollTo(id:anchor:)` works correctly, anchors are respected.
- Using `.scrollPosition.scrollTo(id:anchor:)` ignores the anchor, always positions the target at the same place.
Use this as a proof-of-bug or platform inconsistency.
*/
struct ContentView: View {
@State private var scrollPosition = ScrollPosition(idType: Int.self)
/// Helper that flips the intended anchor to demonstrate that anchors do not work
var shouldBeTopAnchor: Bool {
guard let id = scrollPosition.viewID as? Int else { return true }
if id <= 50 {
return true
} else {
return false
}
}
var body: some View {
VStack {
Text("PROOF: .scrollPosition.scrollTo ignores anchor, .scrollViewProxy respects anchor.\nTap the button below, and compare the behavior with tap-to-scroll in the list items.")
.foregroundColor(.red)
.multilineTextAlignment(.center)
.padding(.bottom)
Button("[BUG] .scrollPosition.scrollTo(50, anchor: \(shouldBeTopAnchor ? ".top" : ".center")) → Anchor is IGNORED") {
// This should scroll to item 50 with the requested anchor, but SCROLLPOSITION IGNORES THE ANCHOR.
if shouldBeTopAnchor {
// Expected: Scroll item 50 to top, but actually scrolls to bottom
scrollPosition.scrollTo(id: 50, anchor: .top)
} else {
// Expected: Scroll item 50 to center, but actually scrolls to top
scrollPosition.scrollTo(id: 50, anchor: .center)
}
}
// Section: Working Example – ScrollViewProxy respects anchor
ScrollViewReader { proxy in
ScrollView {
LazyVStack(spacing: 12) {
ForEach(0..<100, id: \.self) { index in
Text("Item \(index). Tap me!")
.frame(maxWidth: .infinity, minHeight: 44)
.background(index == 50 ? Color.blue.opacity(0.2) : Color.secondary.opacity(0.1))
.cornerRadius(8)
.id(index)
.onTapGesture {
// [WORKS] proxy.scrollTo(50, anchor: .center) correctly centers the item.
proxy.scrollTo(50, anchor: .center)
}
}
}
.scrollTargetLayout()
}
}
}
// Section: Broken Example – .scrollPosition ignores anchor
.scrollPosition($scrollPosition)
}
}
#Preview {
ContentView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment