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?
CodePudding user response:
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()
}
}
}
CodePudding user response:
Something close to this would be a common way of doing what you want.
actor SimpleActor: ObservableObject {
func getString() -> String {
return "some value"
}
}
struct SimpleView: View {
@StateObject var actor = SimpleActor()
@State var value: String = ""
var body: some View {
Text(value)
.frame(width: 100, alignment: .leading)
.task {
value = await actor.getString()
}
}
}
.task
is iOS 15 , so could go back to .onAppear
if you need iOS 13 .