2017-04-13 22 views
0

我需要活動指示器在每次發出Web請求時啓動,並在完成後停止。此時指示器將顯示,但.stopAnimation甚至立即執行,並且不等待Web請求完成。在異步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 
} 
+1

也許您的網絡請求是快速;-)。順便說一句:考慮到指標不會停在發生錯誤的情況下。這將是'defer'聲明的一個很好的例子。 – vadian

+0

PS:...和通常的建議:如果在Swift中存在本機Swift對象而不是'NSArray','NSDictionary',則不要使用任何'NSMutable ...'。 – vadian

+0

NSDictionary有什麼替代方法? – t2nator

回答

0

在DispatchQueue之後添加代碼self.theProgressOutlet.stopAnimating()。試試這個

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

試試看看它是否有效。

+0

你可能是想說裏面而不是之後... –

+0

嘗試之後。它爲我工作 –

+0

這也適用於我!謝謝 – t2nator

0

我沒有看到啓動你的UIActivityIndi​​catior的代碼。只需在viewDidLoad中實例化UIActivityIndi​​cator並在task.resume()之前調用ProgressOutlet.startAnimating()。

請記住,這解決了當前代碼的問題。情況發生時,您在一個場景中有多個異步請求,並且activityIndi​​cator需要在流程開始時啓動,並在所有調用成功完成後結束。爲了處理你目前的情況和我剛纔提到的情況,我建議你創建一個實現了內部Queue的包裝類。您也可以創建一個http處理程序類來發出您的所有請求,以便您可以在一個地方處理此過程,並使以後的更改和調試變得更加容易。

0

您應該將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 
} 
0
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { 
//Your code  
     } 
self.theProgressOutlet.stopAnimating() 

它築巢在工作上面:)