Ok ... so I want to call an async function in my .onAppear
function
import SwiftUI
import RealityKit
import RealityKitContent
import MyFoo
struct ContentView: View {
@Environment(MyFoo.self) private var foo: MyFoo
@State private var message : String?
var body: some View {
VStack {
Model3D(
named: "Scene",
bundle: realityKitContentBundle
).padding(.bottom, 50)
if let msg = self.message {
Text(msg)
} else {
Text("No message yet.")
}
}
.padding()
.onAppear(perform: connectToMyFoo)
}
@MainActor
private func connectToMyFoo() {
DispatchQueue.main.async {
Task {
await self.foo.initialize()
// ...
}
}
}
}
But Swift doesn't let me.
First of all, DispatchQueue.main.async
for some inexplicable reason still expects a synchronous closure. THEN if I try to start a task within that to get around it, it loses the isolation and complains that
Passing argument of non-sendable type 'MyFoo' outside of main actor-isolated context may introduce data races; this is an error in the Swift 6 language mode
A message I am growing exceedingly tired of, as I've wasted WAY more time than I care to admit trying to make it go away.
So if not like this, HOW do I run foo.initialize() in the main actor isolate when the whole bloody language doesn't want to cooperate?!
Run foo.initialize()
. Do it on the main actor. Wait until it's done. It shouldn't be so bloody hard.
Ok ... so I want to call an async function in my .onAppear
function
import SwiftUI
import RealityKit
import RealityKitContent
import MyFoo
struct ContentView: View {
@Environment(MyFoo.self) private var foo: MyFoo
@State private var message : String?
var body: some View {
VStack {
Model3D(
named: "Scene",
bundle: realityKitContentBundle
).padding(.bottom, 50)
if let msg = self.message {
Text(msg)
} else {
Text("No message yet.")
}
}
.padding()
.onAppear(perform: connectToMyFoo)
}
@MainActor
private func connectToMyFoo() {
DispatchQueue.main.async {
Task {
await self.foo.initialize()
// ...
}
}
}
}
But Swift doesn't let me.
First of all, DispatchQueue.main.async
for some inexplicable reason still expects a synchronous closure. THEN if I try to start a task within that to get around it, it loses the isolation and complains that
Passing argument of non-sendable type 'MyFoo' outside of main actor-isolated context may introduce data races; this is an error in the Swift 6 language mode
A message I am growing exceedingly tired of, as I've wasted WAY more time than I care to admit trying to make it go away.
So if not like this, HOW do I run foo.initialize() in the main actor isolate when the whole bloody language doesn't want to cooperate?!
Run foo.initialize()
. Do it on the main actor. Wait until it's done. It shouldn't be so bloody hard.
1 Answer
Reset to default 2Define that the function initialize()
runs on the main actor
@MainActor
func initialize() async {
//...
}
and execute it from a task
modifier instead of using DispatchQueue.main.async
.task {
await self.foo.initialize()
}
connectToMyFoo
async, but then Swift STILL complains that I'm passing a "non-sendable"foo
"outside of the main actor-isolated context". So HOW do I bloody KEEP it in the "main actor-isolated context? Like in actual, helpful terms. "Use async", no offence, is about as helpful as a stubbed toe. – User1291 Commented Feb 11 at 2:45