Accessing actor properties synchronously from task-less context
I found a way to do it by using Combine
, like this:
import Combine
actor Foo {
nonisolated let valuePublisher = CurrentValueSubject<Int, Never>(0)
var value: Int = 0 {
didSet {
valuePublisher.value = value
}
}
}
By providing an non-isolated publisher, we can propagate the actor value safely to the outside, since Publisher
s are thread safe.
Callers can either access foo.valuePublisher.value
or subscribe to it from the outside, without requiring an async context.
How to access an actor from within a filter closure
Put the actor's contents in a local let
constant first, then use that local constant in filter
:
Task {
let actorContents = await myActor.contents
let result = list.filter { item in actorContents.contains { $0 == item } }
}
You wouldn't want filter
to use the updated myActor.contents
halfway through, if myActor.contents
changes at some point during the filtering, right? Therefore, make a local copy of it first, and use that.
Also, consider using a Set
for better efficiency:
let actorContents = Set(await myActor.contents)
let result = list.filter { item in actorContents.contains(item) }
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
).
MainActor vs MainActor(unsafe)
The main purpose of @MainActor(unsafe)
is to make incremental adoption of concurrency easier. You can read this in detail explained in the proposal. If you mark your type as @MainActor(unsafe)
if you try to access properties and methods synchronously in code that hasn't adopted async/await
without breaking anything.
For example following code won't compile with only @MainActor
as here actor isolated property accessed from synchronous context:
@MainActor
class SomeViewModel {
let value1 = 0
var value2 = 0
func getValue2() -> Int { value2 }
func setValue2(_ newValue: Int) { value2 = newValue }
}
func doSomething(with viewModel: SomeViewModel) {
_ = viewModel.value1
_ = viewModel.value2 // ERROR: Property 'value2' isolated to global actor 'MainActor' can not be referenced from this synchronous context
_ = viewModel.getValue2() // ERROR: Call to main actor-isolated instance method 'getValue2()' in a synchronous nonisolated context
viewModel.setValue2(3) // ERROR: Call to main actor-isolated instance method 'setValue2' in a synchronous nonisolated context
}
But if you change @MainActor
to @MainActor(unsafe)
there are no more build errors. Note that @MainActor(unsafe)
is only applicable to swift 5 code to make incremental adoption of concurrency easier and in swift 6 it won't have any effect and would behave the same as @MainActor
.
Also @MainActor(unsafe)
is interchangeable with @preconcurrency @MainActor
. You also can use -warn-concurrency
compiler option to get all the errors that you would get with only @MainActor
as warnings.
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 Package Manager with Resources Compile Errors
Self. in Trailing Swift Closures, Meaning and Purpose
Swift Conditional Conformance with Any
How to Read Ansi Escape Code Response Value in Swift
Any Way to Get a Gif as a Background with Swiftui
Macos Playground: How Can Change the Background Color
Where to Implement Nsvaluetransformer for Core Data in Swift
Why Is the Following Giving Me Zero
Check If the Username Exist in Firebase
Animated Curve Line in Swift 3
Swift Check If Value Is of Type Array (Of Any Type)
Swift Generics and Protocols Not Working on Uikit [Possible Bug]
Don't Delete Some Rows from Uitableview
Stanford Calculator App Keeps Crashing
Error: Argument Type Double/String etc. Does Not Conform to Expected Type "Anyobject"
How to Make a Variable from a String