异步 Web 请求后无法让 activity 指标停止

cannot get activity indicator to stop after asynchronous web request

我需要 activity 指示器在发出 Web 请求时启动并在完成后停止。现在指示器将显示,但 .stopAnimation 甚至立即执行,而不是等待 Web 请求完成。

import UIKit


class ViewController: 
UIViewController,UIPickerViewDelegate,UIPickerViewDataSource {

@IBOutlet weak var locationPickerOutlet: UIPickerView!
@IBOutlet weak var theProgressOutlet: UIActivityIndicatorView!

var locationspickerData: [String] = [String]()

override func viewDidLoad() {
    super.viewDidLoad()

    populateLocations()

}


func populateLocations() {

    self.locationspickerData = ["All Locations"]
    let url:URL = URL(string: "http://<web address>")!
    let session = URLSession.shared
    let request = NSMutableURLRequest(url: url)
    request.httpMethod = "GET"
    //request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
    let task = session.dataTask(with: request as URLRequest, completionHandler: {
        (data, response, error) in
        guard let _:Data = data, let _:URLResponse = response  , error == nil else {
            return
        }

        let json: Any?
        do
        {
            json = try JSONSerialization.jsonObject(with: data!, options: [])
        }
        catch
        {
            return
        }
        guard let data_list = json as? NSArray else
        {
            return
        }
        if let locations_list = json as? NSArray
        {

            for i in 0 ..< data_list.count
            {
                if let locations_obj = locations_list[i] as? NSDictionary
                {
                    if let location_name = locations_obj["name"] as? String
                    {
                        self.locationspickerData.append(location_name)
                    }
                }
            }


            self.locationPickerOutlet.delegate = self
            self.locationPickerOutlet.dataSource = self
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
                self.theProgressOutlet.stopAnimating()
            }

        }

    })

    task.resume()

}



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}


func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return locationspickerData.count
}


func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return locationspickerData[row]
}

func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
    let titleData = locationspickerData[row]
    let myTitle = NSAttributedString(string: titleData, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 15.0)!,NSForegroundColorAttributeName:UIColor.blue])
    return myTitle
}

我没有看到启动您的 UIActivityIndi​​catior 的代码。只需在您的 viewDidLoad 中实例化 UIActivityIndi​​cator 并在 task.resume().

之前调用 theProgressOutlet.startAnimating()

请记住,这可以解决您当前代码的问题。情况发生在一个场景中有多个异步请求,并且 activityIndi​​cator 需要在流程开始时启动,并在所有调用成功完成后结束。为了处理您当前的情况和我提到的情况,我建议您创建一个包装器 class 并实现一个内部队列。您还可以创建一个 http 处理程序 class 来发出所有请求,这样您就可以在一个地方处理这个过程,并使以后的更改和调试更容易。

在DispatchQueue 后面添加代码self.theProgressOutlet.stopAnimating()。试试这个

DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
//Your code    
            }
self.theProgressOutlet.stopAnimating()

试试这个,看看它是否有效。

您应该将 hidesWhenStopped 属性 设置为 true 并在恢复 dataTask 之前开始设置 theProgressOutlet 的动画。

theProgressOutlet.hidesWhenStopped = true
theProgressOutlet.startAnimating()

let task = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
    // YOUR CODE HERE
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
//Your code    
        }
 self.theProgressOutlet.stopAnimating()

将它嵌套在上面的工作中:)