如何重构代码以调用主线程上的AppDelegate ?

时间:2021-08-21 07:34:19

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 -

我最近开始将我的项目从Swift3/Xcode8迁移到Swift4/Xcode9。我的应用程序在运行时崩溃,因为主线程清理程序允许访问UIApplication.shared.delegate只在主线程上,导致启动时崩溃。我有以下代码,在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.

我代码中的其他类可以访问appDelegate。我需要找到一种方法来返回uiapplication . shar.delegate从主线程返回。

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.

注意:使用一个DispatchQueue.main。从何处访问appDelegate不是一个选项。只需要在静态var appDelegate声明中使用它。

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

主线程检查器:在后台线程上调用的UI API: -[UIApplication delegate] PID: 1094, TID: 30824,线程名:(无),队列名:NSOperationQueue 0x60400043c540 (QOS:未指定),QOS: 0

3 个解决方案

#1


6  

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!

#2


4  

A possible solution is to make appDelegate a static stored property of the AppDelegate class which is initialized when the application delegate is created:

一种可能的解决方案是将appDelegate类的静态存储属性设置为:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    static var appDelegate: AppDelegate!

    override init() {
        super.init()
        AppDelegate.appDelegate = self
    }

    // ...
}

Then the application delegate can be retrieved as

然后可以检索应用程序委托作为

 AppDelegate.appDelegate

from any thread.

从任何线程。

(Exactly one instance of the application delegate is created in UIApplicationMain() which is called at application startup, which means that the property is initialized when the application run loop starts.)

(应用程序委托的一个实例是在UIApplicationMain()中创建的,该实例在应用程序启动时被调用,这意味着在应用程序运行循环启动时,属性被初始化。)

#3


0  

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
    }

#1


6  

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!

#2


4  

A possible solution is to make appDelegate a static stored property of the AppDelegate class which is initialized when the application delegate is created:

一种可能的解决方案是将appDelegate类的静态存储属性设置为:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    static var appDelegate: AppDelegate!

    override init() {
        super.init()
        AppDelegate.appDelegate = self
    }

    // ...
}

Then the application delegate can be retrieved as

然后可以检索应用程序委托作为

 AppDelegate.appDelegate

from any thread.

从任何线程。

(Exactly one instance of the application delegate is created in UIApplicationMain() which is called at application startup, which means that the property is initialized when the application run loop starts.)

(应用程序委托的一个实例是在UIApplicationMain()中创建的,该实例在应用程序启动时被调用,这意味着在应用程序运行循环启动时,属性被初始化。)

#3


0  

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
    }