【发布时间】:2022-01-09 14:18:31
【问题描述】:
已更新以提供完整的可重现示例。
我有一个视图MainView 有两个子视图MainTextView 和TableOfContentsView。我想在TableOfContentsView 中选择一个项目,它会触发MainTextView 中的滚动位置变化。
我在MainView 中有一个@State var scrollPosition: Int,它被传递给MainTextView 中的@Binding var scrollPosition: Int。这是我的 3 个视图的代码。
struct MainView: View {
@State private var showingToc = false
@State private var scrollPosition = 0
var body: some View {
VStack(alignment: .leading) {
Text("Table of Contents (chapter \(scrollPosition + 1))")
.onTapGesture {
showingToc = !showingToc
}
Divider()
if showingToc {
TableOfContentsView(
onChapterSelected: { chapter in
scrollPosition = chapter
showingToc = false
}
)
} else {
MainTextView(scrollPosition: $scrollPosition)
}
}
}
}
struct TableOfContentsView: View {
var onChapterSelected: (Int) -> Void
var body: some View {
ScrollView {
VStack {
ForEach(0 ..< 20) { i in
Text("Chapter \(i + 1)")
.onTapGesture {
onChapterSelected(i)
}
}
}
}
}
}
struct MainTextView: View {
let lorumIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
@Binding var scrollPosition: Int
@State private var scrollProxy: ScrollViewProxy? = nil
var body: some View {
ScrollView {
ScrollViewReader { proxy in
VStack(alignment: .leading) {
ForEach(0 ..< 20) { i in
VStack(alignment: .leading) {
Text("Chapter \(i + 1)")
.frame(maxWidth: .infinity, alignment: .center)
.padding(.top)
Text(lorumIpsum)
.font(.system(size: 18, design: .serif))
.padding(.top)
}
.padding(.bottom, 20)
.id(i)
}
}
.padding(.leading)
.padding(.trailing)
.onAppear {
scrollProxy = proxy
}
}
}
.onChange(of: scrollPosition) { target in
scrollProxy?.scrollTo(target, anchor: .top)
}
}
}
我的 .onChange 函数永远不会被调用 - 如果我在里面放置一个断点,它永远不会到达断点。我在这里想念什么?如何观察从视图外部更改的@Binding?
【问题讨论】:
-
需要最小可重现示例
-
这个方法---- onChange(of: scrollPosition) { target in proxy.scrollTo(target, anchor: .top) } in MainTextView会在滚动位置改变时触发。在此块之外使用 proxy.scrollTo。
-
已更新以提供可重现的示例
-
@MattRobertson 可重现的示例按预期滚动。您是在设备/模拟器上运行还是使用 Swift 预览?请注意,在最近的 Xcode 更新中,断点支持已从 Swift 预览中删除。除了断点,还有其他一些你期待的行为吗?
-
@mani 我在 iPhone 13 模拟器上运行。当我选择一个新章节时,Binding 值会更新,但滚动位置不会改变,如果我在调用滚动位置更改的行上放置断点,则永远不会到达。