SwiftUI Shape的path(in:)未按预期顺序调用导致图形绘制异常
核心原理说明
@State 状态更新机制
SwiftUI 中 @State 的变更不会立刻触发视图重绘:所有在主队列当前 RunLoop 循环内发生的 @State 修改,都会被系统批量收集,等当前正在执行的函数(包含你触发状态变更的多步逻辑函数)完全执行完毕后,才会统一触发一次视图刷新,不会每修改一次状态就立刻触发重绘流程。因此你在同一个函数内先执行 drawings.append(drawing),再执行后续其他逻辑时,不会出现 append 执行完立刻回调 path(in:) 的情况。
Shape 的 path(in:) 触发时机
path(in:) 方法仅会在以下两种场景被调用:
- 关联的 Shape 视图首次渲染时
- 该 Shape 依赖的可观测状态(比如你绑定的
drawings数组、其他传入的@Binding/@State属性)发生变更,且 SwiftUI 判定该 Shape 需要重绘时,会在视图刷新阶段统一调用该方法生成新的绘制路径
斜线问题根因
你在 verticalAssignment() 这类多步逻辑函数中,同时修改了 drawings 数组和后续路径计算需要用到的坐标类变量,由于所有状态变更会等整个函数执行完成才会统一触发重绘,path(in:) 执行时读取到的已经是所有状态修改完成后的最终值,而非你执行 drawings.append 时的中间状态,因此路径坐标计算不符合预期,才会生成斜线。
可行解决方案
- 方案1:如果需要分步状态变更触发分步重绘,可以把需要分步执行的逻辑拆分到不同的 RunLoop 循环执行,比如用
DispatchQueue.main.asyncAfter(deadline: .now() + 0)包裹后续逻辑,让第一步的状态变更先触发一次重绘,再执行后续操作 - 方案2:调整状态设计,把路径计算所需的所有坐标参数和单个
drawing元素绑定,每个drawing元素自带完整的起点、终点坐标,不要依赖全局共享的状态变量计算路径,这样无论什么时候触发path(in:),每个drawing的坐标都是固定值,不会受后续变量修改的影响
内容的提问来源于stack exchange,提问作者Sergio Bost
相关产品推荐
相关产品推荐

