scrollTo( ... anchor: .top) 没按预期工作
我正在使用macOS 26.1和 Xcode 26.2。
我在Mac上开发一个计算机的软件模拟器,想要有一个面板显示当前栈(栈向下增长)。注意,我的内存数组以字为单位,而不是字节,因此在把“地址”转换为内存数组的索引时会出现 /2的情况。我是一名有经验的程序员,但对SwiftUI相对比较陌生。
我希望SP的地址始终位于ScrollView的顶部,本以为在scrollTo中指定“anchor .top”就能做到;但实际它总是滚动最小的距离以使该行可见,因此在向下滚动时SP显示在底部,向上滚动时显示在顶部。如果我对anchor的作用理解有误,是否还有其他方式来实现我的目标?
我尝试添加按钮手动滚动到特定点(包括常量和cpu.SP),得到的也是同样的行为。如果我在0x2000处滚动到0x3000,0x3000会在底部显示;如果我在0x3000处滚动到0x2000,它会在顶部显示。把anchor改成.bottom或 .center似乎没有明显效果,所以我猜anchor的作用不是我以为的那样;但如果是这样,它到底起到什么作用?
这个视图的当前代码是:
truct StackView: View {
@State private var position: ScrollPosition = ScrollPosition(edge: .top)
var body: some View {
VStack {
Text("Stack")
ScrollView{
LazyVStack(alignment: .leading, spacing: 0) {
ForEach(0..<0x8000) { index in
Text(String(format: " %04X: %05d/%06d/0x%04X", index*2, cpu.memory[index], Int16(bitPattern: cpu.memory[index]), cpu.memory[index]))
.monospaced()
.id(index)
}
}
.scrollTargetLayout()
}
.scrollPosition($position)
.frame(maxWidth: .infinity, maxHeight: 690)
.border(Color.black)
.onChange(of: cpu.SP) { oldValue, newValue in
let destination = Int(cpu.SP/2)
withAnimation(.easeInOut(duration: 0.3)) {
position.scrollTo(id: destination, anchor: .top)
}
}
}
}
}
解决方案
你描述的编程式滚动的行为如下:
它总是滚动最小的距离以使该行可见,因此在向下滚动时SP显示在底部,在向上滚动时显示在顶部
这听起来就像在没有为 .scrollPosition 修饰符提供锚点时,滚动的通常行为。实际上,这一点在页面关于“接受一个可选值绑定”的变体的 讨论 中有说明:
如果没有提供锚点,SwiftUI在使用滚动位置以编程方式滚动到视图时,将滚动最小的距离。
有趣的是,这句话在针对“接受 ScrollPosition 绑定”的变体的 等效页面 中却缺失,所以我不清楚这个变体的行为是否不同。不过你可以尝试提供一个锚点,看看是否有帮助:
.scrollPosition($position, anchor: .top)
如果仍然无效,你可以尝试把状态变量 position 改成一个可选的 Int,以防它的行为不同。