Search code examples
swiftmacosswiftuiactor

SwiftUI: Actors and Views - Mutable capture of 'inout' parameter 'self' is not allowed in concurrently-executing code


I have my data stored in an Actor. I need to display the data on a view. The only way I have found to do this is to spin up a task to load the data by using an await command on the actor. This doesn't feel right as it is very clunky; it is also giving me an error which I don't understand.

Mutable capture of 'inout' parameter 'self' is not allowed in concurrently-executing code

This is my code:

actor SimpleActor
{
    func getString() -> String
    {
        return "some value"
    }

}

struct SimpleView: View
{
    var actor: SimpleActor
    @State var value: String
    
    init()
    {
        actor = SimpleActor()
        
        Task
        {
            value = await actor.getString() // error here
        }
    }
    
    var body: some View
    {
        Text(value)
            .width(100, alignment: .leading)
    }
}

What is the best way of doing this?


Solution

  • There are a lot of issues in the code. For example you cannot modify a simple property without marked as @State(Object). And you cannot initialize a property (without default value) inside a Task.

    Basically declare the actor as @StateObject and adopt ObservableObject

    Further get the value in the .task modifier and give value a default value

    actor SimpleActor : ObservableObject
    {
        func getString() -> String
        {
            return "some value"
        }
    
    }
    
    struct DetailView: View
    {
        @StateObject var actor = SimpleActor()
        @State private var value = ""
        
        var body: some View
        {
            Group {
                Text(value)
            }.task {
                value = await actor.getString()
            }
                
        }
    }