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

SwiftUI中offset后置gesture导致CPU满载、UI无响应问题排查

为什么SwiftUI中offset修饰符位置错误会导致拖拽无限循环?

问题核心原因

你的问题出在SwiftUI修饰符的顺序和手势的坐标基准逻辑上:

  • 当把offset放在gesture之后时:
    每次在onChanged里修改currentPosition,offset会立刻改变View的显示位置。但DragGesture的value.translation是基于View的当前渲染位置计算的——View位置一变,手势的坐标基准也跟着变了,这会让手势再次检测到"新的拖拽偏移",重新触发onChanged,再次修改currentPosition,进而再次更新offset。
    这种连锁反应形成了无限循环,所以控制台会反复打印"DragEffectViewModifier-ondrag",CPU被持续占用导致满载,UI直接失去响应。

  • 当把offset放在gesture之前时:
    gesture绑定在offset调整前的View"原始布局位置"上,拖拽的translation基准点固定在View的初始位置,不会因为offset改变而变化。此时修改currentPosition只会改变View的显示位置,不会影响手势的偏移计算,自然不会触发循环。

修正后的代码

把offset移到gesture前面即可解决问题:

struct ContentView: View {
    @State private var currentPosition: CGSize = .zero
    @State private var newPosition: CGSize = .zero
    
    var body: some View {
        Image(systemName: "globe")
            .imageScale(.large)
            .foregroundColor(.accentColor)
            .offset(x: currentPosition.width, y: currentPosition.height) // 移到gesture前面
            .gesture(DragGesture()
                .onChanged { value in
                    print("DragEffectViewModifier-ondrag")
                    currentPosition = CGSize(width: 0, height: value.translation.height + newPosition.height)
                }
                .onEnded { value in
                    newPosition = currentPosition
                })
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 16:03:10