Accessing an actor's isolated state from within a SwiftUI view
You need to use MainActor
on your view model (named Model
) indicating that all dispatching in it be on main thread (of course assuming you will use new swift concurrency system for it).
So it would look like
@MainActor
class Model: ObservableObject {
@Published var num: Int = 0
func updateNumber(_ newNum: Int) {
self.num = newNum
}
}
Note: I'd recommend to make all updates inside class, because someone in some place might forget to update it in right way.
Swift, actor: Actor-isolated property 'scanning' can not be mutated from a non-isolated context
How can I use an actor to store/read state information correctly so the MyObj can use it to read and set state?
You cannot mutate an actor's instance variables from outside the actor. That is the whole point of actors!
Instead, give the actor a method that sets its own instance variable. You will then be able to call that method (with await
).
Actor-isolated property cannot be passed 'inout' to 'async' function call
I think the issue comes from Thing
being a struct
. A mutating
func on a struct will assign a new value to the thing
property on the Controller
. In order for that to work, thing
is treated as an inout
parameter in the call to thing.increment()
.
If you make thing an actor
instead of a struct
then increment()
won't need to be a mutating func
and so thing
won't be treated as an inout
parameter.
A possible workaround is to make a copy of the struct first, then call the mutating func on the copy, then store it back on the property in the controller.
func mutate() async {
var thing = self.thing
await thing.increment()
self.thing = thing
print(thing.counter)
}
The reason it's an issue is the UIViewControllers are all actors now, so the properties are considered actor isolated. There is a nonisolated
keyword but it cant be applied to stored properties so it doesn't seem to help here.
If the controller is changed to be an actor
, the error message changes a bit to say that.
error: cannot call mutating async function 'increment()' on actor-isolated property 'thing'
await thing.increment()
^
SwiftUI Using @MainActor with EnvironmentKey
Have you tried adding the main actor attribute to your environment key properties as follows?:
View Model Class:
extension HomeView {
@MainActor
internal final class ViewModel: ObservableObject {
// More code here...
}
}
EnvironmentKey for view model:
struct HomeViewModelKey: EnvironmentKey {
@MainActor
static var defaultValue = HomeView.ViewModel()
}
extension EnvironmentValues {
@MainActor
var homeViewModel: HomeView.ViewModel {
get { self[HomeViewModelKey.self] }
set { self[HomeViewModelKey.self] = newValue }
}
}
Why is it that triggering a function from within a view updates the @State variable, but triggering that same function from another view does not?
This was solved using ObservableObjects
.
How to use URLSession in MainActor
Does it also run on main thread
No. That's the whole point of saying await
. At that moment, the system can switch contexts to a background thread without you knowing or caring. Moreover, at await
your code pauses without blocking — meaning that while you're waiting for the download, the main thread is free to do other work, the user can interact with your app, etc. Don't worry be happy.
Related Topics
Swift 3 Google Map Add Markers on Touch
In Swift 3.1, Unsafemutablepointer.Initialize(From:) Is Deprecated
Accessing an Actor's Isolated State from Within a Swiftui View
Arkit - Getting "Unexpectedly Found Nil" When Using Scn File > 300 Mb
How to Refresh The Google Map in My Application Using Swift
Arrayliteralconvertible: Just a Normal Protocol
Filter on Calayer Except for a Shape Which Is an Union of (Non Necessarily Distinct) Rectangles
How to Make a Function to Accept Any Enum Types That Have a Rawvalue of String
Xcode 13.1 Bug Editing Dependency as Local
Get Applicationdidfinishlaunching Call in a View Controller. Parse Not Initialized Yet
Swift 4 Date Picker Wrong Value Using Minuteinterval
Key Data Not Storing to Icloud with Nsubiquitouskeyvaluestore.Defaultstore
How to Change The Data Type in Realm Database
Need Clarification of Type Casting Operator in Swift
Xcode Issue: Library Not Loaded: @Rpath/Libswiftappkit.Dylib
Why Do I Have to Explicitly Unwrap My String in This Case
How to Calculate Quadrangle for Visible Part of Vertical Plane