iOS 应用程序在 swift 中关闭视图后冻结

Posted

技术标签:

【中文标题】iOS 应用程序在 swift 中关闭视图后冻结【英文标题】:iOS app freezes after dismiss view in swift 【发布时间】:2017-01-26 00:15:20 【问题描述】:

我的问题是,我有两个 viewControllers 与普通 A--->B 一样的模态 segue 连接,A 具有文本字段、开关、按钮和 mapView 等控件,我可以在其中获取 userLocation。 B 目前只有一个按钮和一个 mapView,但是当我点击退出按钮时,它确实成功关闭了 viewController B 并显示 A 只有控件被冻结,不能再点击任何东西,我不知道为什么。有什么帮助吗?

B码

import UIKit
import MapKit
import Parse
import CoreLocation

class MapaMososViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate 

    @IBOutlet weak var mapMozosFollow: MKMapView!

    var totlaAutomozo: String!
    var fechaRegistro: String!


    override func viewDidLoad() 
        super.viewDidLoad()


        mapMozosFollow.delegate = self

        mapMozosFollow.showsUserLocation = true
        mapMozosFollow.showsTraffic = false
        mapMozosFollow.showsScale = false
        print(mapMozosFollow.userLocation.location)


    

    override func viewDidAppear(_ animated: Bool) 

        self.displayError(error: "Exito", message: "Tu pago ha sido procesado, en unos momentos atenderemos tu orden. Total es de $\(totlaAutomozo!) la fecha registrada \(fechaRegistro!)")

    
    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
    


    override func viewWillDisappear(_ animated: Bool) 

    
    @IBAction func salirTapped(_ sender: UIButton) 


            self.dismiss(animated: true, completion: 

                print("here dismissing")
            )



    

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 

        print(locations.last!.coordinate)
        centerMapOnLocation(locations.last!)
    
    let regionRadius: CLLocationDistance = 2000

    func centerMapOnLocation(_ location: CLLocation) 
        let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
                                                                  regionRadius * 2.0, regionRadius * 2.0)
        mapMozosFollow.setRegion(coordinateRegion, animated: true)
    




编辑 1:ViewController 代码。

import UIKit
import Parse
import MapKit
import BraintreeDropIn
import Braintree

class ViewController: UIViewController, PayPalPaymentDelegate, PayPalFuturePaymentDelegate, PayPalProfileSharingDelegate, CLLocationManagerDelegate, UITextFieldDelegate, MKMapViewDelegate, BTDropInViewControllerDelegate 


    @IBOutlet weak var scrollView: UIScrollView!

    @IBOutlet weak var mapaLugar: MKMapView!
    @IBOutlet weak var numeroExteriorTextField: UITextField!
    @IBOutlet weak var telefonoTextField: UITextField!


    @IBOutlet weak var lavadoSwitch: UISwitch!
    @IBOutlet weak var lavadoYAspiradSwitch: UISwitch!


    @IBOutlet weak var numeroCarrosTextField: UITextField!
    @IBOutlet weak var numeroMinivanTextField: UITextField!
    @IBOutlet weak var numeroPickUpsTextField: UITextField!
    @IBOutlet weak var numeroVansTextField: UITextField!


    @IBOutlet weak var numeroAspiradoCarrosTextField: UITextField!
    @IBOutlet weak var numeroAspiradoMinivanTextField: UITextField!
    @IBOutlet weak var numeroAspiradoPickUpsTextField: UITextField!
    @IBOutlet weak var numeroAspiradoVansTextField: UITextField!


    @IBOutlet weak var botonRealizarPedido: UIButton!
    @IBOutlet weak var botonInstrucciones: UIButton!


    @IBOutlet weak var totalLabel: UILabel!

    var showAlertFirstTime: Bool = true

    var locationManager: CLLocationManager = CLLocationManager()
    var ubicacion: CLLocationCoordinate2D!

    var environment:String = PayPalEnvironmentSandbox 
        willSet(newEnvironment) 
            if (newEnvironment != environment) 
                PayPalMobile.preconnect(withEnvironment: newEnvironment)
            
        
    

    var braintreeClient: BTAPIClient?

    let defaults = UserDefaults.standard

    var resultText = "" // empty
    var payPalConfig = PayPalConfiguration() // default

    var total: NSDecimalNumber!

    var vistaDeMozos: Bool = false


    var fechaRegistro: String!
    var totalToSend: String!


    @IBOutlet weak var constrainSizeMap: NSLayoutConstraint!

    override func viewDidLoad() 
        super.viewDidLoad()

        botonInstrucciones.backgroundColor = UIColor(colorLiteralRed: (200.0/255.0), green: 0.0, blue: 0.0, alpha: 1.0)
        botonInstrucciones.layer.cornerRadius = 3
        botonInstrucciones.layer.borderWidth = 2
        botonInstrucciones.layer.borderColor = UIColor.clear.cgColor
        botonInstrucciones.layer.shadowColor = UIColor(colorLiteralRed: (100.0/255.0), green: 0.0, blue: 0.0, alpha: 1.0).cgColor
        botonInstrucciones.layer.shadowOpacity = 1.0
        botonInstrucciones.layer.shadowRadius = 1.0
        botonInstrucciones.layer.shadowOffset = CGSize(width: 0, height: 3)


        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.requestAlwaysAuthorization()

        self.locationManager.startUpdatingLocation()

        NotificationCenter.default.post(name: Notification.Name(rawValue: "keyPressed"), object: nil)

        numeroCarrosTextField.delegate = self
        numeroMinivanTextField.delegate = self
        numeroPickUpsTextField.delegate = self
        numeroVansTextField.delegate = self

        numeroAspiradoCarrosTextField.delegate = self
        numeroAspiradoMinivanTextField.delegate = self
        numeroAspiradoPickUpsTextField.delegate = self
        numeroAspiradoVansTextField.delegate = self

        do 

            if defaults.object(forKey: "clientId") == nil || clientId == "000" 

                let idTest = try PFCloud.callFunction("newCutomer", withParameters: nil)
                print(idTest)
                clientId = idTest as! String
                defaults.set(clientId, forKey: "clientId")

             else 

                print(self.clientId)
            

         catch let error 

            print(error)
        

        if defaults.object(forKey: "clientId") == nil 

         else 

            clientId = defaults.string(forKey: "clientId")!
            print(clientId)
        


       fetchClientToken()


        NotificationCenter.default.addObserver(
            self,
            selector: #selector(ViewController.keyboardWillShow(notification:)),
            name: NSNotification.Name.UIKeyboardWillShow,
            object: nil
        )
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(ViewController.keyboardWillHide(notification:)),
            name: NSNotification.Name.UIKeyboardWillHide,
            object: nil
        )

        scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.interactive

        let touch = UITapGestureRecognizer(target: self, action: #selector(ViewController.singleTapGestureCaptured(gesture:)))
        scrollView.addGestureRecognizer(touch)

    

    func singleTapGestureCaptured(gesture: UITapGestureRecognizer)
        self.view.endEditing(true)
    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)

        if showAlertFirstTime 


            showAlertFirstTime = false
         else 

        
      

    override func viewWillAppear(_ animated: Bool) 
        super.viewWillAppear(animated)
        PayPalMobile.preconnect(withEnvironment: environment)

        print("stop test")

     
    @IBAction func realizarPedidoTapped(_ sender: UIButton) 


        let numeroExterior = numeroExteriorTextField.text!
        let numeroMotosLavado = numeroCarrosTextField.text!
        let numeroDeportivosLavado = numeroMinivanTextField.text!
        let numeroCarroLavado = numeroPickUpsTextField.text!
        let numeroCamionLavado = numeroVansTextField.text!
        let numeroMotoLavadoAspirado = numeroAspiradoCarrosTextField.text!
        let numeroDeportivoLavadoAspirado = numeroAspiradoMinivanTextField.text!
        let numeroCarroLavadoAspirado = numeroAspiradoPickUpsTextField.text!
        let numeroCamionLavadoAspirado = numeroAspiradoVansTextField.text!
        let numeroTelefono = telefonoTextField.text!

        if numeroExterior == "" || numeroTelefono == "" 


            displayError("Error", message: "Te falto llenar tu numero exterior y/o telefono")

         else 

            //Braintree init
            self.braintreeClient = BTAPIClient(authorization: clientToken)



        let items = [item1]
        let subtotal = PayPalItem.totalPrice(forItems: items)

        //var subtotal = PayPalItem.totalPrice(forItems: items)
        let shipping = NSDecimalNumber(string: "0.00")
        let tax = NSDecimalNumber(string: "0.00")

        //details ???

        let paymentDetails = PayPalPaymentDetails(subtotal: subtotal, withShipping: shipping, withTax: tax)

        self.total = subtotal.adding(shipping).adding(tax)

        let payment = PayPalPayment(amount: total, currencyCode: "MXN", shortDescription: "Automozo inc", intent: .sale)

        payment.items = items
        payment.paymentDetails = paymentDetails

        print("\(payment.localizedAmountForDisplay)")


        self.showDropIn(clientTokenOrTokenizationKey: clientToken)

        if (payment.processable) 

            let paymentViewController = PayPalPaymentViewController(payment: payment, configuration: payPalConfig, delegate: self)

        
        else 

            print("Payment not processalbe: \(payment.description)")
            print("payment not processable \(payment)")

            displayError("Error", message: "Hubo un error al procesar tu pago, por favor intenta de nuevo.")

            
        
    

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) 

        super.prepare(for: segue, sender: sender)
        if segue.identifier == "MapaMozosSegue" 

            let mapaMozosVC = segue.destination as! MapaMososViewController
            mapaMozosVC.totlaAutomozo = totalToSend!
            mapaMozosVC.fechaRegistro = fechaRegistro
            locationManager.stopUpdatingLocation()
        
    

    func textFieldDidEndEditing(_ textField: UITextField) 

        textField.resignFirstResponder()
        print("test text field ended")

        if textField.text == "" 

            textField.text = "0"
        

        var numeroCarrosLavadoVar = numeroCarrosTextField.text!
        var numeroMinivansLavadoVar = numeroMinivanTextField.text!
        var numeroPickUpsLavadoVar = numeroPickUpsTextField.text!
        var numeroVansLavadoVar = numeroVansTextField.text!

        var numeroCarrosLavadoAspiradoVar = numeroAspiradoCarrosTextField.text!
        var numeroMinivansLavadoAspiradoVar = numeroAspiradoMinivanTextField.text!
        var numeroPickUpsLavadoAspiradoVar = numeroAspiradoPickUpsTextField.text!
        var numeroVansLavadoAspiradoVar = numeroAspiradoVansTextField.text!

        if numeroCarrosLavadoVar == "" 
            numeroCarrosLavadoVar = "0"
            numeroCarrosTextField.text = "0"
        
        if numeroMinivansLavadoVar == "" 
            numeroMinivansLavadoVar = "0"
            numeroMinivanTextField.text = "0"

        
        if numeroPickUpsLavadoVar == "" 
            numeroPickUpsLavadoVar = "0"
            numeroPickUpsTextField.text = "0"
        
        if numeroVansLavadoVar == "" 
            numeroVansLavadoVar = "0"
            numeroVansTextField.text = "0"

        
        if numeroCarrosLavadoAspiradoVar == "" 
            numeroCarrosLavadoAspiradoVar = "0"
            numeroAspiradoCarrosTextField.text = "0"
        
        if numeroMinivansLavadoAspiradoVar == "" 
            numeroMinivansLavadoAspiradoVar = "0"
            numeroMinivanTextField.text = "0"

        
        if numeroPickUpsLavadoAspiradoVar == "" 
            numeroPickUpsLavadoAspiradoVar = "0"
            numeroAspiradoPickUpsTextField.text = "0"
        
        if numeroVansLavadoAspiradoVar == "" 
            numeroVansLavadoAspiradoVar = "0"
            numeroVansTextField.text = "0"


        

        let priceOfLavadoCarro = Int(numeroCarrosLavadoVar)! * pricesLavado["LavadoCarro"]!
        let priceOfLavadoMinivan = Int(numeroMinivansLavadoVar)! * pricesLavado["LavadoMinivan"]!
        let priceOfLavadoPickUp = Int(numeroPickUpsLavadoVar)! * pricesLavado["LavadoPickUp"]!
        let priceOfLavadoVan = Int(numeroVansLavadoVar)! * pricesLavado["LavadoVan"]!

        //Lavado y Aspirado

        let priceOfLavadoYAspiradoCarro = Int(numeroCarrosLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoCarro"]!
        let priceOfLavadoYAspiradoMinivan = Int(numeroMinivansLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoMinivan"]!
        let priceOfLavadoYAspiradoPickUp = Int(numeroPickUpsLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoPickUp"]!
        let priceOfLavadoYAspiradoVan = Int(numeroVansLavadoAspiradoVar)! * pricesLavadoYAspirado["LavadoYAspiradoVan"]!

        let totalAutomozo = priceOfLavadoCarro + priceOfLavadoMinivan + priceOfLavadoPickUp + priceOfLavadoVan + priceOfLavadoYAspiradoCarro + priceOfLavadoYAspiradoMinivan + priceOfLavadoYAspiradoPickUp + priceOfLavadoYAspiradoVan

        print(totalAutomozo)

        totalLabel.text = "\(totalAutomozo).00"

        textField.resignFirstResponder()
    

    func textFieldShouldEndEditing(_ textField: UITextField) -> Bool 

        if (textField.text?.characters.count)! == 1 

            print("text quota meet")
            textField.resignFirstResponder()
            self.view.endEditing(true)

            return true

         else 

            textField.text = "0"
        

        return true
    


    let regionRadius: CLLocationDistance = 100

    func centerMapOnLocation(_ location: CLLocation) 
        let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
                                                                  regionRadius * 2.0, regionRadius * 2.0)
        mapaLugar.setRegion(coordinateRegion, animated: true)
    

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) 

        centerMapOnLocation(locations.last!)
        ubicacion = locations.last!.coordinate

   
    // Mark - Braintree methods

    func showDropIn(clientTokenOrTokenizationKey: String) 

        var value: Bool = false
        var totlaAutomozo = self.totalLabel.text

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM dd YYYY HH:mm"
        dateFormatter.timeZone = NSTimeZone.local


        fechaRegistro = dateFormatter.string(from: Date())

        let request =  BTDropInRequest()
        request.amount = "\(total)"
        request.currencyCode = "MXN"
        print(request.description)
        BTUIKAppearance.darkTheme()
        BTUIKAppearance.sharedInstance().activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
//            request.
        let dropIn = BTDropInController(authorization: clientTokenOrTokenizationKey, request: request)
         (controller, result, error) in
            if (error != nil) 
                print("ERROR")
             else if (result?.isCancelled == true) 
                print("CANCELLED")
             else if let result = result 
                // Use the BTDropInResult properties to update your UI




                print(result.paymentOptionType)
                print("payment method: \(result.paymentMethod?.nonce)")
                print("ppayment desc \(result.paymentDescription)")
                print(result.paymentIcon.description)

                value = self.postNonceToServer(paymentMethodNonce: (result.paymentMethod?.nonce)!)


                
                controller.dismiss(animated: true, completion: nil)


                if value 

                    self.locationManager.stopUpdatingLocation()

                    self.performSegue(withIdentifier: "MapaMozosSegue", sender: self)

                    self.vistaDeMozos = true

                 else 

                    self.displayError("Alerta", message: "El pedido ha sido cancelado exitosamente.")

                    //top row
                    self.numeroCarrosTextField.text = "0"
                    self.numeroMinivanTextField.text = "0"
                    self.numeroPickUpsTextField.text = "0"
                    self.numeroVansTextField.text = "0"

                    //bottom row
                    self.numeroAspiradoCarrosTextField.text = "0"
                    self.numeroAspiradoMinivanTextField.text = "0"
                    self.numeroAspiradoPickUpsTextField.text = "0"
                    self.numeroAspiradoVansTextField.text = "0"

                    //data
                    self.telefonoTextField.text = ""
                    self.telefonoTextField.text = ""
                
            
            self.present(dropIn!, animated: true, completion: nil)

    

    func userDidCancelPayment() 
        self.dismiss(animated: true, completion: nil)
    

    func postNonceToServer(paymentMethodNonce: String) -> Bool 

        var val = true

        do 
            var response = try PFCloud.callFunction("checkout", withParameters: ["payment_method_nonce":paymentMethodNonce, "amount":"\(total!).00", "customerId": clientId])
            print(response)

         catch let error 

            print(error.localizedDescription)
        

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM. dd, YYYY HH:mm"
        dateFormatter.timeZone = NSTimeZone.local

        fechaRegistro = dateFormatter.string(from: Date())


        let usuarioPagado: PFObject = PFObject(className: "Ordenes")
        let location: PFGeoPoint = PFGeoPoint(latitude: ubicacion.latitude, longitude: ubicacion.longitude)
        usuarioPagado["Ubicacion"] = location
        usuarioPagado["NumeroExterior"] = numeroExteriorTextField.text!
        usuarioPagado["NumeroDeTelefono"] = telefonoTextField.text!
        usuarioPagado["LavadoCarro"] = numeroCarrosTextField.text!
        usuarioPagado["LavadoMiniVan"] = numeroMinivanTextField.text!
        usuarioPagado["LavadoPickUp"] = numeroPickUpsTextField.text!
        usuarioPagado["LavadoDeVan"] = numeroVansTextField.text!
        usuarioPagado["LavadoAspiradoCarro"] = numeroAspiradoCarrosTextField.text!
        usuarioPagado["LavadoAspiradoMiniVan"] = numeroAspiradoMinivanTextField.text!
        usuarioPagado["LavadoAspiradoPickUp"] = numeroAspiradoPickUpsTextField.text!
        usuarioPagado["LavadoAspiradoDeVan"] = numeroAspiradoVansTextField.text!
        usuarioPagado["Monto"] = totalLabel.text!
        usuarioPagado["NumeroDeTelefono"] = telefonoTextField.text!
        usuarioPagado["TipoDeCelular"] = "iPhone"
        usuarioPagado["FechaDeOrden"] = fechaRegistro

        self.totalToSend = self.totalLabel.text!

                usuarioPagado.saveInBackground() 
                    (success: Bool, error: Error?) -> Void in

                    if error == nil 

                        //done
                        print("saved object")
                        val = false

                     else 

                        //not done
                        print("not saved because \(error?.localizedDescription)")

                    
                

        numeroCarrosTextField.text = "0"
        numeroMinivanTextField.text = "0"
        numeroPickUpsTextField.text = "0"
        numeroVansTextField.text = "0"

        numeroAspiradoCarrosTextField.text = "0"
        numeroAspiradoMinivanTextField.text = "0"
        numeroAspiradoPickUpsTextField.text = "0"
        numeroAspiradoVansTextField.text = "0"
        totalLabel.text = "00.00"
        self.lavadoSwitch.isOn = false
        self.lavadoYAspiradSwitch.isOn = false

        self.numeroExteriorTextField.text = ""
        self.telefonoTextField.text = ""

        self.numeroCarrosTextField.isHidden = true
        self.numeroMinivanTextField.isHidden = true
        self.numeroPickUpsTextField.isHidden = true
        self.numeroVansTextField.isHidden = true

        self.numeroAspiradoCarrosTextField.isHidden = true
        self.numeroAspiradoMinivanTextField.isHidden = true
        self.numeroAspiradoPickUpsTextField.isHidden = true
        self.numeroAspiradoVansTextField.isHidden = true
    return val

    

    func drop(inViewControllerDidLoad viewController: BTDropInViewController) 

        print("did load view drop")

    

    func drop(inViewControllerDidCancel viewController: BTDropInViewController) 

        print("did cancel drop payment")

    

    func drop(inViewControllerWillComplete viewController: BTDropInViewController) 

        print("drop will complete payment")

    

    func drop(_ viewController: BTDropInViewController, didSucceedWithTokenization paymentMethodNonce: BTPaymentMethodNonce) 

        var totlaAutomozo = totalLabel.text

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM dd YYYY HH:mm"
        dateFormatter.timeZone = NSTimeZone.local


        fechaRegistro = dateFormatter.string(from: Date())

        print("did succeeded with tokenization")
        print(" \(paymentMethodNonce.nonce)")

        var value = postNonceToServer(paymentMethodNonce: paymentMethodNonce.nonce)



        self.dismiss(animated: true, completion: nil)


        if value 

            displayError("Exito", message: "Tu pago ha sido procesado, en unos momentos atenderemos tu orden. Total es de $\(totlaAutomozo ?? "00.00") la fecha registrada \(fechaRegistro)")


         else 

            self.displayError("Error", message: "Hubo un error al guardar tu informacion, ponte en contacto con nosotros.")
        

    

    func fetchClientToken() 

        do 

            let response = try PFCloud.callFunction("generateToken", withParameters: ["clientId": clientId])
           self.clientToken = response as! String



         catch let error 

            print(error)
        
    

    func keyboardWillShow(notification:NSNotification)

        var userInfo = notification.userInfo!
        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        keyboardFrame = self.view.convert(keyboardFrame, from: nil)

        var contentInset:UIEdgeInsets = self.scrollView.contentInset
        contentInset.bottom = keyboardFrame.size.height
        self.scrollView.contentInset = contentInset
    

    func keyboardWillHide(notification:NSNotification)

        let contentInset:UIEdgeInsets = UIEdgeInsets.zero
        self.scrollView.contentInset = contentInset
    

    func scrollViewDidScroll(_ scrollView: UIScrollView) 
        self.view.endEditing(true)

    

    func showFullMap() 


        if vistaDeMozos 

            self.telefonoTextField.isHidden = true
            self.botonRealizarPedido.isHidden = true
            self.lavadoSwitch.isHidden = true
            self.lavadoYAspiradSwitch.isHidden = true
            self.botonRealizarPedido.isHidden = true

            self.numeroExteriorTextField.isHidden = true

            self.numeroCarrosTextField.isHidden = true
            self.numeroMinivanTextField.isHidden = true
            self.numeroPickUpsTextField.isHidden = true
            self.numeroVansTextField.isHidden = true


            self.numeroAspiradoCarrosTextField.isHidden = true
            self.numeroAspiradoMinivanTextField.isHidden = true
            self.numeroAspiradoPickUpsTextField.isHidden = true
            self.numeroAspiradoVansTextField.isHidden = true

            self.view.layoutSubviews()
         else 


        
    

【问题讨论】:

检查你的 deinit 方法是否被调用,并且你的 viewcontroller 在你第一次关闭时被成功释放。 deinit // 在这里检查 如果有,那么问题可能出在你的 A 视图控制器上,没有贴出来。 在“B代码”中不要忘记调用viewDidAppear中的超级实现,viewWillDisappear。也许它也可以解决您的问题。 可能相关:***.com/q/39608231 【参考方案1】:

您是否尝试使用调试器暂停应用程序以检查堆栈帧?有时这可以帮助您发现死锁或无限循环。您会在代码编辑器和调试器之间的栏中找到暂停按钮(如果调试器被隐藏,则在底部):

在 Xcode 窗口左侧的 Debug Navigator 中查看堆栈帧。你能看出什么可疑的吗?这是一个堆栈帧,表明应用程序在主运行循环中处于空闲状态:

这通常是完全正常的,因为应用正在等待用户输入。如果您看到类似以下内容,您可能正在处理死锁:

信号量会阻止线程继续运行,直到其他线程再次打开信号量。如果两个或多个线程停止等待对方,您正在处理死锁。如果涉及主线程,应用程序将被冻结。

我能想到的第三种可能是主线程上的无限循环:

当然,这个很容易发现 :) 堆栈帧中较暗的条目来自您自己的代码。您可以单击这些条目以查找确切位置并使用调试器检查变量。其他条目将向您展示程序集。

如果您通过暂停调试器没有发现任何可疑之处,我将开始一点一点地删除这些代码部分,并尝试每次都重现问题。有两种可能的结果:

    您删除了一些看起来无害的代码,然后它突然按预期工作了。然后,您可以仔细查看您删除的代码,从而更容易找出问题所在。

    您最终会得到一个显示该问题的最小项目。这现在更容易调试和推理,因为没有其他东西会分散您对问题的注意力。当您的代码示例尽可能小时,您从同事或 Stack Overflow 获得帮助的可能性也更高。

第三个攻击向量正在检查 View Debugger:

    冻结的视图控制器上方是否有任何透明视图阻止用户事件?

    是否在涉及的控件和视图上启用了用户交互?选择一个视图并检查右侧的 Object Inspector:

【讨论】:

是的,我有一个死锁,我可以看到 semaphore_wait_trap() 有没有办法知道我从哪里得到它? 检查您是否看到任何有助于其他正在运行的线程的内容。看看你是否可以从阻塞线程的跟踪中推断出任何信息。这可能是一项艰巨的侦探工作。如果没有任何帮助,请按照我的建议将项目减少到最低限度并发布另一个问题。 我会先在A 中注释掉viewWillAppear,但这只是一种预感......【参考方案2】:

尝试删除DispatchQueue.main.async 否则A viewController 将不会收到通知。它的交互已被禁用,因为 segue

//DispatchQueue.main.async 
  self.dismiss(animated: true, completion: 
    print("here dismissing")
  )
//

【讨论】:

完成我已更改为 ti 没有帮助,我看到发生了一些奇怪的事情。解除 VC B 后,它返回 A 去 self.dismiss(animated: true, completion: print("heredismissing") ) 这样做并返回 B 完成怎么来?【参考方案3】:

确保检查是否有任何 NSDelayedPerforming 方法阻塞了主线程(Foundation > NSRunloop)。即 performSelector afterDelay...

就我而言(Objective-C),我必须在 ViewController 的 viewDidDisappear 实例方法中使用 cancelPreviousPerformRequestsWithTarget。

[NSObject cancelPreviousPerformRequestsWithTarget:self];

我认为这同样适用于使用 NSTimer.scheduledTimerWithTimeInterval (Swift) 而不会在正确的生命周期方法中使计时器失效。

【讨论】:

以上是关于iOS 应用程序在 swift 中关闭视图后冻结的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中关闭键盘时,UIToolbar 不再显示在视图中

在 iOS 7 SDK 中关闭 UIAlertview 后 UIView 没有响应

firebase 在 Swift 中关闭重载表?

如何检查视图控制器是不是已在 Swift 中关闭

如何在 Swift 中关闭和完成处理程序后获取数据

在 SWIFT 中关闭 segue 之前保存变量