'How do I refactor my code to call AppDelegate on the main thread?
I recently started migrating my project from Swift3/Xcode8 to Swift4/Xcode9. My app crashes at runtime because the main thread sanitizer allows access to UIApplication.shared.delegate
only on the main thread, resulting in a crash at startup. I have the following code, which worked fine in Swift 3 -
static var appDelegate: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate;
}
Other classes in my code make access to appDelegate. I need to figure out a way to return UIApplication.shared.delegate
from the main thread.
Note: Using an DispatchQueue.main.async{}
block from wherever access is made to appDelegate
is not an option. Need to use it only within the static var appDelegate
declaration only.
Looking for a clever workaround.
Relevant crash message:
Main Thread Checker: UI API called on a background thread: -[UIApplication delegate] PID: 1094, TID: 30824, Thread name: (none), Queue name: NSOperationQueue 0x60400043c540 (QOS: UNSPECIFIED), QoS: 0
Solution 1:[1]
Solved by using Dispatch Groups.
static var realDelegate: AppDelegate?;
static var appDelegate: AppDelegate {
if Thread.isMainThread{
return UIApplication.shared.delegate as! AppDelegate;
}
let dg = DispatchGroup();
dg.enter()
DispatchQueue.main.async{
realDelegate = UIApplication.shared.delegate as? AppDelegate;
dg.leave();
}
dg.wait();
return realDelegate!;
}
and call it somewhere else for
let appDelegate = AppDelegate(). realDelegate!
Solution 2:[2]
I use the following:
static var shared: AppDelegate? {
if Thread.isMainThread {
return UIApplication.shared.delegate as? AppDelegate
}
var appDelegate: AppDelegate?
DispatchQueue.main.sync {
appDelegate = UIApplication.shared.delegate as? AppDelegate
}
return appDelegate
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Durul Dalkanat |
Solution 2 | Debaprio B |