主线程检查器:在后台线程上调用 UI API:-[UIApplication delegate] 冻结应用程序

问题描述 投票:0回答:3

每当我的应用程序从 JSON 获取数据时,有时会收到此警告并且应用程序会立即冻结:

主线程检查器:在后台线程上调用的 UI API:-[UIApplication delegate]

PID:7439,TID:362794,线程名称:(无),队列名称:NSOperationQueue 0x60000002f7c0(QOS:未指定),QoS:0 回溯:

谁能解释一下如何摆脱它?

ios swift multithreading background-thread
3个回答
4
投票

看起来您正在从非主线程的线程更新 UI 上的某些内容。

你的问题没有太多可说的。 但如果您使用 JSON,则可能会异步检索它。确保每当您从检索到的内容更新 UI 时,都通过类似

之类的方式将其包装在对主线程的调用中
dispatch_async(dispatch_get_main_queue(), ^{
// code to post to UI
});

2
投票

在最新版本的 swift / Xcode / 模拟器中,即使检查 UI 控件的值也可能会抛出此错误。

关于这个主题有大量的问题和资源。例如:

详尽教程

所以回答

但这就是我猜你想要的:

DispatchQueue.main.async {
    // Access UI stuff here
}

2
投票

每当我的应用程序从 json 获取数据时

因此您应该从获取该数据的代码开始。您可能在后台线程上调用

[[UIApplication sharedApplication] delegate]
。这是不允许的。

这可能意味着您正在使用应用程序委托作为存储模型数据的位置。你不应该这样做。 应用程序中几乎没有地方应该引用应用程序委托。(这是一个非常常见的错误,因为有时为了简单起见,它在示例代码中完成。)

如果程序崩溃,该位置应该在堆栈跟踪中,所以我会首先查看那里,但否则,您需要审核您的代码(可能围绕 JSON 解析或网络请求)以找到您在哪里执行此操作.


正如下面的评论中所指出的,没有快速解决此问题的方法,并且几乎可以肯定您的代码变得不太稳定,并且更有可能在现场崩溃。也就是说,在 Swift 中创建一个单例来保存全局值看起来像这样:

class SomeSingleton {
    static let shared = SomeSingleton()
    // Properties you want to be available via the singleton
}

您可以通过以下方式访问它:

SomeSingleton.shared.<property>

这不会使任何东西成为线程安全的,但如果单例的属性是不可变的(

let
),那么可以在任何线程上安全地调用通过
SomeSingleton.shared
获取它们,这与
UIApplication.shared.delegate
不同。

再次,听起来这段代码中存在严重的并发问题,并且这不是一个快速解决方案;它只是一种经常使用的工具,而不是在 AppDelegate 上添加随机值。

© www.soinside.com 2019 - 2024. All rights reserved.