异步 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
}
我没有看到启动您的 UIActivityIndicatior 的代码。只需在您的 viewDidLoad 中实例化 UIActivityIndicator 并在 task.resume().
之前调用 theProgressOutlet.startAnimating()
请记住,这可以解决您当前代码的问题。情况发生在一个场景中有多个异步请求,并且 activityIndicator 需要在流程开始时启动,并在所有调用成功完成后结束。为了处理您当前的情况和我提到的情况,我建议您创建一个包装器 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()
将它嵌套在上面的工作中:)
我需要 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
}
我没有看到启动您的 UIActivityIndicatior 的代码。只需在您的 viewDidLoad 中实例化 UIActivityIndicator 并在 task.resume().
之前调用 theProgressOutlet.startAnimating()请记住,这可以解决您当前代码的问题。情况发生在一个场景中有多个异步请求,并且 activityIndicator 需要在流程开始时启动,并在所有调用成功完成后结束。为了处理您当前的情况和我提到的情况,我建议您创建一个包装器 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()
将它嵌套在上面的工作中:)