原因:'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'

reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'

我的应用程序在添加检查通知允许功能之前运行良好。当我添加那个函数时,我遇到了这个奇怪的崩溃,它给出了 'Modifications to layout engine must not be performed from a background thread after it has been accessed from the main thread' 的错误。调试时弹出的代码是这样的。有什么想法吗?

我的代码

import UIKit
import GoogleMaps

class HomeViewController: FHBaseViewController {
    var devices : [Device]?
    var firstLoad = true;
    let defaults = UserDefaults.standard;
    var icons: [String:UIImage] = [:];
    
    
    
    
    @IBOutlet weak var movingView : UIView!;
    @IBOutlet weak var stoppedView : UIView!;
    @IBOutlet weak var inYardView : UIView!;
    @IBOutlet weak var offlineView : UIView!;
    @IBOutlet weak var statsView : UIView!;
    @IBOutlet weak var mapBed : UIView!;
    @IBOutlet weak var mapView : GMSMapView!;
    
    
    @IBOutlet weak var morningLabel : UILabel!;

    @IBOutlet weak var movingLabel : UILabel!;
    @IBOutlet weak var stoppedLabel : UILabel!;
    @IBOutlet weak var inYardLabel : UILabel!;
    @IBOutlet weak var offlineLabel : UILabel!;
    
    @IBOutlet weak var nameLabel : UILabel!;
    
    override func viewDidLoad() {
        super.viewDidLoad();
        
        self.reloadData();
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated);
        self.tabBarController?.tabBar.isHidden = false;
        if firstLoad{
            firstLoad = false;
        }else{
            if UserService.userInfo != nil{
                self.reloadData();
            }
        }
    
    }
    
    override func connectionResume() {
        self.reloadData()
    }
    
    
    func checkNotificationAllowed(){
        let data = defaults.object(forKey:"mute") as? Bool
        print(data!)
        if (data != nil) == true {
            let current = UNUserNotificationCenter.current()
            current.getNotificationSettings(completionHandler: { permission in
                switch permission.authorizationStatus  {
                case .authorized:
                    print("User granted permission for notification")
                case .denied:
                    print("User denied notification permission")
                    
                    let alert = UIAlertController(title: "Turn On Notifications".localized(), message: "Notifications are disabled. Please turn on app notifications to get device alerts.".localized(), preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "Don't Allow".localized(), style: .cancel, handler: { action in
                        self.dismiss(animated: true, completion: nil)
                    }))
                    alert.addAction(UIAlertAction(title: "Allow".localized(), style: .destructive, handler: { action in
                        self.dismiss(animated: true, completion: nil)
                    }))
                    self.present(alert, animated: true, completion: nil)
                    
                case .notDetermined:
                    print("Notification permission haven't been asked yet")
                case .provisional:
                    // @available(iOS 12.0, *)
                    print("The application is authorized to post non-interruptive user notifications.")
                case .ephemeral:
                    // @available(iOS 14.0, *)
                    print("The application is temporarily authorized to post notifications. Only available to app clips.")
                @unknown default:
                    print("Unknow Status")
                }
            })
        }
    }
    
    func showLoginVC(){
        UserService.clearUser();
        UserService.clearLocalCacheUser();
        self.firstLoad = true;
        if buildType == "GPSTracker" {
            let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MarocLoginViewController") as! MarocLoginViewController;
            loginVC.successBlock = { (resp, password) in
                self.loginSuccess(resp, password: password);
            }
            loginVC.modalPresentationStyle = .fullScreen
            self.present(loginVC, animated: true, completion: {});
        } else {
            let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController;
            loginVC.successBlock = { (resp, password) in
                self.loginSuccess(resp, password: password);
            }
            loginVC.modalPresentationStyle = .fullScreen
            self.present(loginVC, animated: true, completion: {});
        }
        
    }
    
    func loginSuccess(_ resp: LoginResponse?, password: String){
        if let un = resp?.userName, let name = resp?.name, let apiToken = resp?.apiToken{
            let u = User(username: un, name: name, password: password, apiToken: apiToken, isActive: true, baseUrl: Configuration.getBaseUrl());
            UserService.setUser(user: u);
        }
        
        self.reloadData();
    }
    
    func reloadData(){
        self.nameLabel.text = UserService.userInfo?.name;
        self.mapView.clear();
        let update = GMSCameraUpdate.zoom(to: 1);
        self.mapView.moveCamera(update);
        self.showHud();
        DashBoardService.getDashBoard { (resp) in
            self.hideHud();
            if resp?.status == 1{
                self.movingLabel.text = "\(resp?.summary?.moving ?? 0)";
                self.stoppedLabel.text = "\(resp?.summary?.stopped ?? 0)";
                self.inYardLabel.text = "\(resp?.summary?.inyard ?? 0)";
                self.offlineLabel.text = "\(resp?.summary?.offline ?? 0)";
                
                DispatchQueue.main.async {
                    self.hideHud();
                    self.checkNotificationAllowed()
                }
            }
        }
        
        DeviceService.getDevice { (resp) in
            if resp?.status == 1{
                self.devices = resp?.devices;
                self.reloadMap();
            }
        }
        
        
    }
}

问题的产生是因为后台线程正在显示警报,因为 getNotificationSettings 中的完成处理程序正在后台线程中 运行。为防止在主线程中出现此崩溃警报,请在您的代码中进行以下更改。

func checkNotificationAllowed(){
    let data = defaults.object(forKey:"mute") as? Bool
    print(data!)
    if (data != nil) == true {
        let current = UNUserNotificationCenter.current()
        current.getNotificationSettings(completionHandler: { permission in
            switch permission.authorizationStatus  {
            case .authorized:
                print("User granted permission for notification")
            case .denied:
                print("User denied notification permission")
                DispatchQueue.main.async {[weak self] in
                      guard let weakSelf = self else {return}

                      let alert = UIAlertController(title: "Turn On Notifications".localized(), message: "Notifications are disabled. Please turn on app notifications to get device alerts.".localized(), preferredStyle: .alert)
                      alert.addAction(UIAlertAction(title: "Don't Allow".localized(), style: .cancel, handler: { action in
                             weakSelf.dismiss(animated: true, completion: nil)
                      }))
                      alert.addAction(UIAlertAction(title: "Allow".localized(), style: .destructive, handler: { action in
                             weakSelf.dismiss(animated: true, completion: nil)
                      }))
                      weakSelf.present(alert, animated: true, completion: nil)
                }
            case .notDetermined:
                print("Notification permission haven't been asked yet")
            case .provisional:
                // @available(iOS 12.0, *)
                print("The application is authorized to post non-interruptive user notifications.")
            case .ephemeral:
                // @available(iOS 14.0, *)
                print("The application is temporarily authorized to post notifications. Only available to app clips.")
            @unknown default:
                print("Unknow Status")
            }
        })
    }
}