[英]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.