You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中ScrollView消失时调用scrollTo方法触发崩溃如何解决?

崩溃原因

你遇到的崩溃核心原因是:

  • 用if-else控制Scroll视图显隐时,Scroll会在tabCount为偶数时被完全移出视图树,内部ScrollViewReader对应的proxy对象也会被销毁
  • 父视图的MagnificationGesture在任意时刻都会修改全局的current状态,如果你刚好在手势触发时切换了tabCount,Scroll销毁的瞬间current的变化会触发onChange回调,调用已经被销毁的proxy的scrollTo方法,导致野指针崩溃

解决方案

方案1:优化显隐逻辑避免视图销毁(最简便)

把if-else的视图移除逻辑改成用opacity控制可见性,Scroll不会被销毁,proxy始终有效,还能自动保存滚动位置,下次显示时保持原位置:

// 替换ContentView里原来的if-else代码
ZStack {
    Text("some text")
        .opacity(tabCount%2 == 0 ? 1 : 0)
    Scroll(current: $current)
        .opacity(tabCount%2 == 0 ? 0 : 1)
}

方案2:加安全校验避免无效调用

如果需要保留if-else的销毁逻辑,就给滚动逻辑加双重校验,避免调用已销毁的proxy:

  1. 首先修改Scroll视图,新增可见性判断,不可见时不执行滚动:
struct Scroll:View {
    @Binding var current:CGFloat
    let isVisible: Bool // 新增可见性参数
    
    let intRandom = Int.random(in: 1..<18)

    var body: some View {
        ScrollViewReader { proxy in
            HStack {
                Button("Foreword"){
                    proxy.scrollTo(9, anchor: .center)
                }
            }
            ScrollView(.horizontal) {
                HStack {
                    ForEach(0..<20) { item in
                        RoundedRectangle(cornerRadius: 25.0)
                            .frame(width: 100, height: 40)
                            .overlay(Text("\(item)").foregroundColor(.white))
                            .id(item)
                    }
                }
                .onChange(of: current) { value in
                    guard isVisible else { return } // 不可见时跳过滚动逻辑
                    proxy.scrollTo(13, anchor: .center)
                }
            }
        }
    }
}
  1. 优化父视图手势逻辑,Scroll不可见时不修改current值:
let magni = MagnificationGesture()
    .onChanged(){ value in
        guard tabCount%2 != 0 else { return }
        current = value
    }
    .onEnded { value in
        guard tabCount%2 != 0 else { return }
        if current > 2 {
            self.tabCount += 1
        }
        final = current + final
        current = 0
    }
  1. 调用Scroll时传入可见性参数:
Scroll(current: $current, isVisible: tabCount%2 != 0)

内容的提问来源于stack exchange,提问作者ikunhub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 04:06:03