Swift并发:在非隔离区域为何要使用被主Actor隔离的Sendable类型全局变量?

移动开发 2026-07-09

我已经启用易用的并发,默认隔离设为主(MainActor)。我这边有这段代码:

private let arc_total_degrees: CGFloat = 180 + 18
private let arc_start_degrees: CGFloat = 180 - 9


fileprivate struct MeterArcShape: Shape {
  func path(in rect: CGRect) -> Path {
    let radius = rect.width/2
    var path = Path()
    path.addArc(
      center: CGPoint(x: radius, y: radius),
      radius: radius,
      startAngle: Angle(degrees: arc_start_degrees),
      endAngle: Angle(degrees: arc_end_degrees),
      clockwise: false)
    return path
  }
}

我收到了警告:

属于MainActor隔离的let 'arc_start_degrees' 不能在非隔离上下文中被引用

然而,CGFloat 应该是可发送的(Sendable),而我使用的是 let。这意味着不会产生数据竞争。为什么Swift会阻止我这么做?

我本可以对所有这些fileprivate全局变量使用 nonisolated,但数量太多,逐一标记很烦人。

解决方案

Sendable 不会移除actor隔离。CGFloatSendable,因此该值本身可以安全跨越并发域

但由于默认的actor隔离设置,该声明仍然是 MainActor-isolated。

Shape.path(in:) 是nonisolated,所以它不能同步访问一个属于MainActor隔离的全局常量

将该常量标记为 nonisolated,因为它只是一个静态值,不依赖于UI状态

你还可以把这些常量放在一个专用命名空间下,只对该命名空间标记为 nonisolated

private nonisolated enum Constants {
    static let arc_total_degrees: CGFloat = 180 + 18
    static let arc_start_degrees: CGFloat = 180 - 9
    static let arc_end_degrees: CGFloat = 180 + 9
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章