Ios 无法在异步web请求后停止活动指示器

Ios 无法在异步web请求后停止活动指示器,ios,swift,uiactivityindicatorview,Ios,Swift,Uiactivityindicatorview,我需要活动指示器在web请求发出时启动,完成后停止。此时指示器将显示,但.stopAnimation正在立即执行,而不是等待web请求完成 import UIKit class ViewController: UIViewController,UIPickerViewDelegate,UIPickerViewDataSource { @IBOutlet weak var locationPickerOutlet: UIPickerView! @IBOutlet weak var theP

我需要活动指示器在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
}
导入UIKit
类视图控制器:
UIViewController、UIPickerViewDeleteGate、UIPickerViewDataSource{
@IBOutlet弱var位置PickerOutlet:UIPickerView!
@IBOutlet弱var程序出口:UIActivityIndicator视图!
变量位置SpickerData:[字符串]=[字符串]()
重写func viewDidLoad(){
super.viewDidLoad()
人口分布
}
func populateLocations(){
self.locationspickerData=[“所有位置”]
让url:url=url(字符串:“http:/”)!
让session=URLSession.shared
let request=NSMutableURLRequest(url:url)
request.httpMethod=“GET”
//request.cachePolicy=NSURLRequest.cachePolicy.reloadIgnoringCacheData
让task=session.dataTask(其中:request作为URLRequest,completionHandler:{
(数据、响应、错误)
保护let:Data=Data,let:URLResponse=response,error==nil-else{
返回
}
有吗?
做
{
json=尝试JSONSerialization.jsonObject(带:data!,选项:[])
}
抓住
{
返回
}
guard let data_list=json作为?NSArray else
{
返回
}
如果let locations\u list=json as?NSArray
{
对于0中的i..Int{
返回1
}
func pickerView(pickerView:UIPickerView,numberOfRowsInComponent:Int)->Int{
返回位置SpickerData.count
}
func pickerView(pickerView:UIPickerView,titleForRow行:Int,forComponent组件:Int)->String{
返回位置SpickerData[行]
}
func pickerView(pickerView:UIPickerView,attributedTitleForRow行:Int,forComponent组件:Int)->NSAttribute字符串{
设titleData=locationspickerData[行]
让myTitle=NSAttributeString(字符串:titleData,属性:[NSFontAttributeName:UIFont(名称:“Georgia”,大小:15.0)!,NSForegroundColorAttributeName:UIColor.blue])
返回我的标题
}

我没有看到启动UIActivityIndicator的代码。只需在视图中实例化UIActivityIndicator,然后在task.resume()之前加载并调用ProgressOutlet.startAnimating()


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

在DispatchQueue之后添加代码self.theProgressOutlet.stopAnimating()。请尝试此操作

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

尝试此操作并查看其是否有效。

在继续执行
数据任务之前,应将
hideswhen stopped
属性设置为
true
,并开始设置
程序出口的动画

theProgressOutlet.hidesWhenStopped = true
theProgressOutlet.startAnimating()

let task = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
    // YOUR CODE HERE
}

嵌套在上面的工作:(

也许您的Web请求是那么快;-)。考虑到指示器在错误的情况下不会停止。这将是一个很好的例子,用于<代码> DEFER STATMENT.PS:…和通常的建议:不要使用任何<代码> nStutabl…< /代码>如果有本地SWIFT对应而不是<代码> NSArray < /代码>,
NSDictionary
在Swift中。NSDictionary还有什么选择?Swift
Dictionary
[String:Any]
)另外,我觉得web请求比它应该的速度慢。只需30-40秒就可以用一列加载13行……有什么想法吗?
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
//Your code    
        }
 self.theProgressOutlet.stopAnimating()