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:
- 首先修改
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) } } } } }
- 优化父视图手势逻辑,
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 }
- 调用
Scroll时传入可见性参数:
Scroll(current: $current, isVisible: tabCount%2 != 0)
内容的提问来源于stack exchange,提问作者ikunhub
相关产品推荐
相关产品推荐

