显示 UIAlert 会使应用程序崩溃吗?

display UIAlert will crash the app on present?

我有一个测试连接操作逻辑。它将实时或不实时测试服务器。当逻辑完成测试并尝试在闭包线程内显示 UIAlertController 时会发生错误,这会使系统崩溃。

@IBAction func TestNetwork(_ sender: Any) {
    var message = "\(internetConnection) internet connection \n \(serverStatus) server\n  "
    self.showSpinner(onView: self.view)
    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
        self.testConnection(connectionTestCompletionHanlder: {connectionResult in


            let alertController = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
            let defaultAction = UIAlertAction(title: "OK", style: .default) { (action) in
                // Respond to user selection of the action.
            }
            alertController.addAction(defaultAction)
            //self.removeSpinner()
            self.present(alertController, animated: true){
                // The alert was presented
            }
        })
    }
}

错误

-[Assert] Cannot be called with asCopy = NO on non-main thread. +[UIView setAnimationsEnabled:] being called from a background thread. Performing any operation from a background thread on UIView or a subclass is not supported and may result in unexpected and insidious behavior.
-Unsupported use of UIKit view-customization API off the main thread. -setHasDimmingView: sent to <_UIAlertControllerView: 0x7ffe2ff8b4a0; frame = (0 0; 375 667); layer = >

-Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'

根据上面的评论,您应该始终在主线程上启动 UI 工作。上面的完成处理程序虽然通过 asyncAfter 在主线程上实例化,但可以在任何线程上执行,因此您需要更改打开警报控制器的部分以明确在主线程上:

//previous code as above...

DispatchQueue.main.async {
  self.present(alertController, animated: true){
    // The alert was present
  }
}

如果您不打算使用它,您也可以将警报控制器的完成处理程序设置为 nil,而不是空闭包。

我遇到了类似的问题。别人遇到的就在这里回答。

应用程序也可能在 iOS 13.3(至少)中崩溃,当显示请求权限的警报时,当您的应用程序使用 SceneDelegate 时,即使 Application Scene Manifest 条目存在于 plist 文件中。 不得不从 info.plist 文件中删除 SceneDelegate 和相关条目,并且不再崩溃。