[英]How to resolve - compiler warning that UndoManager is non-sendable
我有代码,其中一组函数需要在全局参与者上下文下运行,但具有撤消功能。 当我打电话给他们时,我收到以下编译器警告(Xcode 14)。
Non-sendable type 'UndoManager?' passed in call to global actor 'MyActor'-isolated function cannot cross actor boundary
我理解为什么会收到此警告,但不知道如何解决。
这是一些示例代码来说明问题。
@globalActor actor MyActor {
static let shared = MyActor()
}
class MyClass {
@MyActor func doSomething(undoManager: UndoManager?) {
// Do something here
undoManager?.registerUndo(withTarget: self) {
$0.reverseSomething(undoManager: undoManager)
}
}
@MyActor func reverseSomething(undoManager: UndoManager?) {
// Do the reverse of something here
undoManager?.registerUndo(withTarget: self) {
$0.doSomething(undoManager: undoManager)
}
}
}
struct MyView: View {
@Environment(\.undoManager) private var undoManager: UndoManager?
let myObject: MyClass
var body: some View {
Button("Do something") { myObject.doSomething(undoManager: undoManager) } // <- Warning here: Non-sendable type 'UndoManager?' passed in call to global actor 'MyDBActor'-isolated function cannot cross actor boundary
}
}
您要做的是使撤消/重做的注册与正在完成(或撤消)的实际工作保持同步。
但是您也将 model 隔离到自己的 Actor 中。 消息只能在参与者之间异步传递。 Swift 将迫使您明确处理该问题。
为了与 Actor 同步,在这种情况下,同步将通过等待发送到MyActor
的消息来完成工作,然后等待主要 Actor 注册撤消/重做。
所以你将不得不产生一个任务来处理同步。
在下面的示例中,我已经做到了。 我创建了一个等待工作的任务,然后等待执行/撤消的注册。
我的代码引入的问题是,现在整个任务都是异步的。 当您调用“doSomething”时,您实际上并没有这样做……您是在要求主要演员在将来的某个时候这样做。 这可能会也可能不会导致您的代码出现问题。
import SwiftUI
@globalActor actor MyActor {
static let shared = MyActor()
func reallyDoSomething() {
}
func reallyUndoSomething() {
}
}
class MyClass {
@MainActor func doSomething(undoManager: UndoManager) {
Task {
// Do the reverse of something here
await MyActor.shared.reallyDoSomething()
await MainActor.run {
undoManager.registerUndo(withTarget: self) { this in
this.reverseSomething(undoManager: undoManager)
}
}
}
}
@MainActor func reverseSomething(undoManager: UndoManager) {
Task {
// Do the reverse of something here
await MyActor.shared.reallyUndoSomething()
await MainActor.run {
undoManager.registerUndo(withTarget: self) { this in
this.doSomething(undoManager: undoManager)
}
}
}
}
}
struct MyView: View {
@Environment(\.undoManager) private var undoManager: UndoManager?
let myObject: MyClass
var body: some View {
Button("Do something") {
if (nil != undoManager) {
myObject.doSomething(undoManager: undoManager!)
}
} // <- Warning here: Non-sendable type 'UndoManager?' passed in call to global actor 'MyDBActor'-isolated function cannot cross actor boundary
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.