display UIAlert will crash the app on present?

≡放荡痞女 提交于 2020-02-24 11:40:26

问题


I have a test connection action logic. it will test the server in live or not. the bug happens when the logic finishes the test and try display UIAlertController inside closure thread it will crash the systems.

@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
            }
        })
    }
}

error

-[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.'


回答1:


As per the comments above, you should always launch UI work on the main thread. The completion handler you have above, although instantiated on the main thread through the asyncAfter could execute on any thread, so you therefore need to change the section that opens the alert controller to explicitly be on the main thread:

//previous code as above...

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

You could also set the alert controller's completion handler to nil if your are not planning to utilise it, rather than having an empty closure.



来源:https://stackoverflow.com/questions/58735355/display-uialert-will-crash-the-app-on-present

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!