my project uses both Objective-C and Swift code. When a user logs in, it calls a set of apis for user preference, I have a DataCoordinator.swift class which schedules the AP
The answers by @Mark Bridges and @geek1706 are good answers but I would like to add my 2 cents about this matter and give a general example.
As stated above this is a feature in Swift 4 SE-176.
The implementation should still be permitted to detect concurrent conflicting accesses, of course. Some programmers may wish to use an opt-in thread-safe enforcement mechanism instead, at least in some build configurations.
The exclusive access enforces that every write mutation of vars must be exclusive when accessing that variable. In a multithread environment, multiple threads accessing a shared var and one or more can modify it.
There's nothing like a good example:
If we try to mutate a shared value in a multi-threaded environment using an abstraction (mutation occurs on a protocol type) between 2 objects and the Exclusive Access to Memory is on, our app will crash.
protocol Abstraction {
var sharedProperty: String {get set}
}
class MyClass: Abstraction {
var sharedProperty: String
init(sharedProperty: String) {
self.sharedProperty = sharedProperty
}
func myMutatingFunc() {
// Invoking this method from a background thread
sharedProperty = "I've been changed"
}
}
class MainClass {
let myClass: Abstraction
init(myClass: Abstraction) {
self.myClass = myClass
}
func foobar() {
DispatchQueue.global(qos: .background).async {
self.myClass.myMutatingFunc()
}
}
}
let myClass = MyClass(sharedProperty: "Hello")
let mainClass = MainClass(myClass: myClass)
// This will crash
mainClass.foobar()
Since we didn't state that the Abstraction protocol is class bound, during runtime, inside myMutatingFunc, the capture of self will be treated as struct even though we injected an actual class (MyClass).
Escaping variables generally require dynamic enforcement instead of static enforcement. This is because Swift cannot reason about when an escaping closure will be called and thus when the variable will be accessed.
The solution is to bound the Abstraction protocol to class:
protocol Abstraction: class