SwiftUI拖拽手势导致模拟器崩溃问题求助
SwiftUI下拉视图拖拽手势冻结崩溃问题解析
问题现象
为下拉通知视图添加向上拖拽关闭功能时,执行拖拽手势后视图仅移动小段就冻结,进而导致模拟器卡死、Xcode崩溃,但相同逻辑在卡片滑动视图上可正常运行。
核心问题分析
手势绑定对象错误
原代码将拖拽手势绑定在底部的小圆角矩形上,而offset状态却作用在整个通知视图容器上。当拖拽小矩形时,视图因offset变化发生位移,导致手势的坐标参考系不断变动,触发高频的视图重绘与状态更新,最终引发渲染死循环。Offset状态计算逻辑缺陷
onChanged中直接将offset设为gesture.translation,未考虑视图当前的偏移位置。当视图已偏移后,后续的拖拽偏移会出现计算叠加错误,导致状态异常,加剧渲染压力。状态切换条件不合理
modifyState中判断拖拽范围的区间-600...(-100)过大,且未限制offset的最大值,可能导致视图偏移超出预期范围,进一步加重渲染负担。
修复后的代码
import SwiftUI struct MessagesHomeView: View { @State private var offset = CGSize.zero @State var showNotifications: Bool = false var body: some View { VStack { Button { withAnimation(.easeInOut){ showNotifications.toggle() } } label: { Image(systemName: "bell").font(.title) } } .overlay { VStack { if showNotifications { ZStack { Color(UIColor.darkGray) VStack(alignment: .leading){ Text("Notifications").font(.title3).foregroundColor(.white) Spacer() }.padding(10).padding(.top, 70) VStack { Spacer() RoundedRectangle(cornerRadius: 10) .frame(width: 90, height: 9) .foregroundColor(.white) }.padding(.bottom, 4) } .frame(height: 500) .transition(AnyTransition.move(edge: .top).combined(with: .opacity)) .cornerRadius(10, corners: [.bottomLeft, .bottomRight]) .offset(y: offset.height) // 将手势绑定到整个通知视图容器 .gesture( DragGesture() .onChanged { gesture in // 限制仅向上拖拽,且偏移不超过视图高度 let newOffset = gesture.translation.height + offset.height if newOffset < 0 { offset.height = max(newOffset, -500) } } .onEnded { _ in withAnimation(.easeInOut){ modifyState() } } ) Spacer() } }.ignoresSafeArea() } } func modifyState(){ switch offset.height { case -100...(-500): showNotifications = false offset = .zero default: offset = .zero } } }
关键修改点
- 将拖拽手势从底部小矩形移至整个通知视图容器,确保手势坐标参考系稳定
- 调整
offset计算逻辑,基于当前偏移累加拖拽位移,并限制最大向上偏移为视图高度(500),避免过度偏移 - 优化状态切换的区间判断,匹配实际视图高度,确保状态切换逻辑精准
内容的提问来源于stack exchange,提问作者Ahmed Zaidan
相关产品推荐
相关产品推荐

