Before start with actor, Let’s try to understand much more details about data races and Concurrency issues. Accessing same memory from multiple threads called Data race. It’s difficult to track and fix data races.
In Xcode, We have a tool as Thread Sanitizer, which helps us to find data race and solve it by updating our functional approach or code base. We can enable this from XCode. Choose Edit Scheme -> Runtime Sanitization, as shown in the below image
We used Dispatch Queue with locks to avoid process of read, write happening together. In Swift, Actors making our life easier (Released — iOS 15 and Swift 5.5)
Actor helps to write simplified code and no need to use dispatch queue with locks. It makes us write the clean code and understand it easily. Actor insists complier to establish Synchronised access by having Optimised Synchronised process and prevents us from not introducing the data race unknowingly
In concurrent environments, Actors are safe to use and it’s similar to classes. Swift automatically ensures no two pieces of code attempt to access an actor’s data at the same time.
Actors operate similarly like a serial queue for their message inbox and consider requests one at a time. By default these requests execute in the order they were received, but we can also set the task priority.
Actors can be created by “actor” keyword. Actors are reference types same like Classes.
Actors are not allowed to write from outside, with or without await.
Actors do not support inheritance, so they do not support either “final” or “override”.
If we try to access the actor properties as we normally do, the compiler will throw an error as below,
This error will not come for constant properties also data race will not happen for constant properties. Error will come for computed properties as well.
Because we can not be sure when the access will be changed to read/write. To serialize our access to that data, we can use await and async.
Actors has two types of access:
- Non Isolated
All access in the actor is isolated to avoid the data races by default. If we are sure about the property that it won’t raise data race, in that case we can set access level as Non isolated. Non isolated properties can be Initialised and used like below,
The main actor mentioned using the keyword as @MainActor, represents your main thread. On the main dispatch queue, it will perform all its synchronisation. It can be used in all Apple platforms like SwiftUI, AppKit, UIKit, watchKit.
It performs its tasks on the main thread and it is a globally unique actor. To use the main actor, We need to add the @MainActor attribute and It can be either a method or a class. The function will always execute on the main thread while we add @MainActor to a function.
@MainActor attribute can also be used in class. It will make all properties and methods be MainActor. To avoid being a part of the main actor, Nonisolated can be used.
Let’s have a look on sample implementation
We update the age detail in UILabel in the main thread on button action.
The function where we update details, should be mentioned async and UI update can do it here like below,