繁体   English   中英

在Swift中何时何地关闭UIAlertController?

[英]When and where to dismiss UIAlertController in Swift?

我正在调用一个执行URLSession的方法,但是在执行任何URLSession之前,它会呈现一个UIAlertController ,该UIAlertController阻塞UI,直到实现来自请求的某种响应为止。 逻辑告诉我,在主线程上调用UIAlertController的方法的完成块UIAlertController其解散是最好的选择。 我认为这是错误的吗? 显然,如此呈现的UIAlertController确实会显示,但永远不会UIAlertController 救命?

块:

getCostandIV { output in

            let cost = output["ask"] as! NSNumber
            let IV = output["IV"] as! NSNumber

            self.enteredCost = cost.stringValue
            self.enteredIV = IV.stringValue

            DispatchQueue.main.async {

                self.progress.dismiss(animated: true, completion: nil)
                self.tableView.reloadSections(IndexSet(integer: 1), with: UITableView.RowAnimation.none)
                self.canWeSave()

            }

        }

功能:

 func getCostandIV (completionBlock: @escaping (NSMutableDictionary) -> Void) -> Void {

    DispatchQueue.main.async {


        self.progress = UIAlertController(title: "Retrieving ask price and volatility...", message: nil, preferredStyle: UIAlertController.Style.alert)
        self.present(self.progress, animated: true, completion: nil)

    }

    guard let url = URL(string: "https://api.tdameritrade.com/v1/marketdata/chains?apikey=test&symbol=\(symbol)&contractType=\(type)&strike=\(selectedStrike)&fromDate=\(selectedExpiry)&toDate=\(selectedExpiry)") else {
        return
    }

    let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
        guard let dataResponse = data,
            error == nil else {
                //print(error?.localizedDescription ?? "Response Error")

                DispatchQueue.main.async {


                        self.presentedViewController?.dismiss(animated: true, completion: {

                        let alert = UIAlertController(title: "There was an error retrieving ask price and volatility.", message: "Please try again later.", preferredStyle: .alert)
                        alert.addAction(UIAlertAction(title: "OK", style: .default))
                        self.present(alert, animated: true)

                    })

                }

                return }
        do{
            //here dataResponse received from a network request
            let jsonResponse = try JSONSerialization.jsonObject(with:
                dataResponse, options: [])
            //                //print(jsonResponse) //Response result

            guard let jsonDict = jsonResponse as? NSDictionary else {
                return
            }
            //                //print(jsonDict)

            var strikeMap : NSDictionary = [:]

            if self.type == "CALL" {
                strikeMap = jsonDict["callExpDateMap"] as! NSDictionary

            } else {
                strikeMap = jsonDict["putExpDateMap"] as! NSDictionary

            }

            self.strikes.removeAllObjects()

            let inner = strikeMap.object(forKey: strikeMap.allKeys.first ?? "<#default value#>") as! NSDictionary
            let innerAgain = inner.object(forKey: inner.allKeys.first ?? "<#default value#>") as! NSArray
            let dict : NSDictionary = innerAgain[0] as! NSDictionary

            let dict2 = ["ask" : dict["ask"] as! NSNumber, "IV" : dict["volatility"] as! NSNumber] as NSMutableDictionary



            completionBlock(dict2)


        } catch let parsingError {
            print("Error", parsingError)
        }
    }
    task.resume()
}

编辑:使用self.presentedViewController?.dismiss(animated: true, completion: nil)不能解决此问题。 此外,未调用用于self.progress的dismiss函数的完成块。

编辑2:就算在回调之前在警报控制器上调用了present,在回调函数中的dismiss代码之前,presentedViewController也为零。

只有一切顺利,您的警报才会被取消。 我建议您将功能更改为以下形式:

 func getCostandIV (completionBlock: @escaping (NSMutableDictionary?, Error?) -> Void) -> Void

并确保您的completionBlock是当你的所谓的guard声明失败或引发错误。 在您当前的代码中,仅在网络请求失败时才解除警报,而在解析JSON时出现问题时则不会解除。

如果getCostandIV调用getCostandIV方法,则不会显示第二个警报,并且self.progress将引用未显示的警报。

更改

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

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

使用此方法,要消除警报,应在异步块中添加dismiss方法,并为此设置计时器,应告诉异步块从现在开始到5秒开始异步,然后执行以下操作:

        alert.addAction(UIAlertAction(title: "ok", style: .default,
                                      handler: nil))
        viewController.present(alert, animated: true, completion: nil)

        // change to desired number of seconds (in this case 5 seconds)
        let when = DispatchTime.now() + 5
        DispatchQueue.main.asyncAfter(deadline: when){
            // your code with delay
            alert.dismiss(animated: true, completion: nil)
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM