George
George

Reputation: 30451

Converting non-sendable function value may introduce data races

I have a simple piece of code:

struct ContentView: View {
    var body: some View {
        Text("Hello world!")
            .task {
                await myAsyncFunc()
            }
    }

    private func myAsyncFunc() async {}
}

This compiles completely fine. However, if I replace the task with this:

.task(myAsyncFunc)

It doesn't work, and gives me the error below:

Converting non-sendable function value to '@Sendable () async -> Void' may introduce data races

Why is this, and how can I fix it?

Upvotes: 22

Views: 7869

Answers (2)

Patrick
Patrick

Reputation: 2432

This error appears because the function you're passing to the SwiftUI task method is not marked as @Sendable, meaning it might access non-thread-safe data concurrently, leading to data races. The @Sendable attribute ensures the function can be safely used in concurrency.

You need to do two things:

  1. Annotate the function with @Sendable:
@Sendable private func myAsyncFunc() async {}
  1. Annotate the struct with @MainActor:
@MainActor
struct ContentView: View {
  ...
}

Upvotes: 4

George
George

Reputation: 30451

As it states, the function can be marked as @Sendable. This is used to prevent data races.

Change it to this:

@Sendable private func myAsyncFunc() async {}

Note that the @Sendable must be before the access modifier.

Upvotes: 19

Related Questions