主要演员的 init 是否在 Swift 中被隔离(Xcode Beta 5)

问题描述 投票:0回答:1

以下代码在 Xcode 16 Beta 4 中运行良好,但在 beta 5 中无法编译:


@MainActor
class TimerSchudler {
  init() {
  }
}

class GameScene: SKScene {
  let scheduler = TimerSchudler()
  
  override init() {
    super.init()
  }
  
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

我收到此错误:

属性“self.scheduler”未在 super.init 调用时初始化

然后我将

scheduler
初始化移动到
init
内:

class GameScene: SKScene {
  let scheduler: TimerSchudler
  
  override init() {
    scheduler = TimerSchudler()
    super.init()
  }
  
}

这成为警告:

在同步非隔离上下文中调用主参与者隔离初始化程序“init()”;这是 Swift 6 语言模式下的错误

这意味着

TimerScheduler
的 init 函数现在位于主要角色上。

如果我将其更改为使用非主要演员的演员:


actor TimerSchudler {
  init() {
  }
}

class GameScene: SKScene {
  let scheduler: TimerSchudler
  
  override init() {
    scheduler = TimerSchudler()
    super.init()
  }
  
  required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

这个编译得很好。这意味着非主要参与者的 init 仍然是非隔离的。

我的理解是所有参与者的 init 都应该是非隔离的。然而,看起来在 Beta 5 中,Apple 将 MainActor 的 init 设为 main actor 隔离。这是有问题的,因为

SKScene
的 init 不在主要演员上。因此,如果我像这样将 init 标记为主要参与者:

class GameScene: SKScene {
  let scheduler: TimerSchudler

  @MainActor
  override init() {
    scheduler = TimerSchudler()
    super.init()
  }
}

我会收到警告:

主参与者隔离初始化器“init()”与非隔离重写声明具有不同的参与者隔离;这是 Swift 6 语言模式下的错误

那么我该如何解决这个问题?

ios swift concurrency
1个回答
0
投票

所有参与者的 init 都应该是非隔离的

正确。

Apple 将 MainActor 的 init 设为 main actor 隔离

您没有启动“MainActor”。您在与 MainActor 隔离的类(不是 Actor)上调用

init
。是的,那个
init
位于 MainActor 上,因为它继承了
@MainActor
属性。 (再次强调,属性。它不是一个 Actor。它是一个与 MainActor 隔离的类。)

那么我该如何解决这个问题?

您提供了方法并说“这编译得很好。”

如果需要,您还可以将

TimeSchudler.init
标记为非隔离:

@MainActor
class TimerSchudler {
    nonisolated init() {
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.