Swift 3 - 活动指标延迟或没有响应

时间:2016-12-15 14:55:08

标签: json autolayout swift3 delay

当您使用内容填充字段时,我有字段和按钮,然后单击按钮:

@IBAction func dpSomething(_ sender: UIButton) {
    activityIndicator.startAnimating()
    activityIndicator.isHidden = false
    field.isHidden = true
    send.isHidden = true
    let url = "http://urlwithjson"
    let session = URLSession.shared
    DispatchQueue.main.async { [unowned self] in
        let task = session.dataTask(with: URL(string: url)!) { (data, response, error) in
            if(error==nil){
                        do {
                            let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                                if((jsonData["response"] as! Int) == 0){
                                    self.responseL.text = "no results"
                                }
                            self.activityIndicator.stopAnimating()
                            self.responseL.isHidden = false
                        } catch _ {}
            }
        }
        task.resume()
    }

}

当我使用打印时,它几乎立即打印出JSON,但活动指示器需要10-20秒消失或有时它不会消失。有人可以告诉我为什么吗?而且当我更改标签中的文本时,我在控制台中收到错误:

  

此应用程序正在从后台线程修改autolayout引擎,这可能导致引擎损坏和奇怪的崩溃。这将在将来的版本中引发异常。

为什么会这样?

2 个答案:

答案 0 :(得分:4)

首先在activityIndicator.startAnimating()之后添加以下代码,此代码将隐藏您调用self.activityIndicator.stopAnimating()的活动指示符:

activityIndicator.hidesWhenStopped = true

如果响应成功,您只是隐藏活动指示器,因此当catch块中出现错误时您可能需要隐藏指示符,当您从api响应中收到错误时,可能需要隐藏指示符

另一点是,当你提出请求时,它不应该在主线程中,只在后台,然后当你需要更新UI然后使用主线程时,所以最后这里是你可能需要的完整代码: / p>

 @IBAction func dpSomething(_ sender: UIButton) {
    activityIndicator.startAnimating()
    activityIndicator.isHidden = false
    activityIndicator.hidesWhenStopped = true
    field.isHidden = true
    send.isHidden = true
    let url = "http://urlwithjson"
    let session = URLSession.shared
    let task = session.dataTask(with: URL(string: url)!) { (data, response, error) in
            if(error==nil){
                do {
                    let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                    if((jsonData["response"] as! Int) == 0){
                        DispatchQueue.main.async {
                        //Update your UI here


                         self.responseL.text = "no results"
                        }
               }

                    DispatchQueue.main.async {
                        //Update your UI here
                        self.activityIndicator.stopAnimating()
                        self.responseL.isHidden = false
                    }

                } catch _ {

                    // JSONSerialization error might happen so hide the indicator
                    DispatchQueue.main.async {
                        //Update your UI here
                        self.activityIndicator.stopAnimating()
                        self.responseL.isHidden = false
                    }

                }
            }else {
                // api response error might happen so hide the indicator
                DispatchQueue.main.async {
                    //Update your UI here
                    self.activityIndicator.stopAnimating()
                    self.responseL.isHidden = false
                }

            }
        }
        task.resume()

}

答案 1 :(得分:2)

您只需对UI线程进行main更改,就不要在主线程上调用异步API调用。

    let task = session.dataTask(with: URL(string: url)!) { (data, response, error) in
        if(error==nil){
                    do {
                        let jsonData = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
                            if((jsonData["response"] as! Int) == 0){
                                self.responseL.text = "no results"
                            }
                        DispatchQueue.main.async {
                            self.activityIndicator.stopAnimating()
                            self.activityIndicator.isHidden = true
                            self.responseL.isHidden = false
                        }
                    } catch _ {}
        }
    }
    task.resume()