Why can't I get the request result form Alamofire

青春壹個敷衍的年華 提交于 2019-11-28 12:16:45

问题


I can't get the result of Alamofire request.So,I created ouput of an array that I got from json async call.I can't get the resultArray out of dispatch {...}.When I add println to debug the code.The second one appear first before the first one. All i want to resultArray to get the data from Alamofire to display in UIPickerView.Please Help!!!

Here is my code

import UIKit
import Alamofire

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource{

@IBOutlet var venuePicker : UIPickerView?

var resultOld = [String:String]() // i need it to get only value from json

var result : [String]?

let refreshControl = UIRefreshControl()

override func viewDidLoad() {

    if result == nil {
        populateVenues ({ (error, result) -> Void in
            self.result = result as? [String]
            self.venuePicker?.reloadAllComponents()
        })
    }
}

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

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    if result != nil{
        return result!.count// Why i can't use result?.count instead of result!.count
    }
    else{
        return 0
    }
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
    if result != nil{
        println(result)
        return result?[row]
    }
    else{
        return "..."
    }
}

func populateVenues(completion : (error: NSError?,result : AnyObject?) -> Void){
    Alamofire.request(.POST, "http://xxxx.xxxx.xxx").responseJSON() {
        (_, _, jsonData, error) in

        if error == nil{
            var venues = JSON(jsonData!)

            for (k, v) in venues {

                self.resultOld[k] = v.arrayValue[0].stringValue
            }

            self.result = self.resultOld.values.array

            completion(error: nil,result: self.result)
        }
        else{
            println("Error!!")
            completion(error: error!,result: nil)
        }
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

Here is my output at console

The 2st result array : []
The 1st result array : [ORIX Kobe Nyusatsu, NPS Sendai Nyusatsu, JU Gunma, KAA Kyoto, JU Ibaraki, USS Gunma, ISUZU Kobe, NAA Osaka Nyusatsu, SMAP Sapporo Nyusatsu, L-Up PKobeNyusatsu, ARAI Sendai, TAA Minami Kyushu, NPS Oyama Nyusatsu, CAA Tokyo, JU Toyama, USS Shikoku, NPS Gifu Nyusatsu, NAA Fukuoka, KCAA Yamaguchi, JU Fukuoka, LAA Kansai, JAA, TAA Kinki, USS Sapporo, JU Miyagi, USS Fukuoka, JU Tokyo]

Please i really need to know what is happening to me and why i can't get the result of async call first.


回答1:


So asynchronous calls are executed on another thread. Thus, when you call the function populateVenue(), the populateVenue() function is not completing before the println("The 2st result array : \(self.resultArray)" ). If you set up your populateVenue() to have a closure, this won't happen. Example:

override func viewDidLoad() {

   super.viewDidLoad()

   populateVenue( { (error, result) -> Void in 
      println("The 2st result array : \(self.resultArray)" )
   })
}

func populateVenue(completion: (error: NSError?, result: AnyObject?) -> Void) {
    Alamofire.request(.POST, "http://localhost:8080/ws/automobile/global/auction/latest/venues").responseJSON() {
    (_, _, jsonData, error) in

       if error == nil {
          // do whatever you need
          // Note that result is whatever data you retrieved
          completion(nil, result)
       } else {
           println("Errror")
           completion(error!, nil)
       }
   }
}

Edit:

I am still trying to understand your problem, but this is my best shot. Note that I have no idea what the purpose of resultOld is so I removed it. If you absolutely need it you can add it back in. My design here is to make the properties optional, and return the result in the completion block. Then in viewDidLoad, you can initialize the property array and reload your screen.

@IBOutlet var venuePicker : UIPickerView?

// Try making this optional so you can tell when the network call is completed
var result: [String]?

var error = "Error"

let refreshControl = UIRefreshControl()

override func viewDidLoad() {
    if result == nil {
       populateVenues ( { (result) -> Void in
          self.result = result
          self.venuePicker?.reloadAllComponents()
       })
    }
}

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

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
     if result != nil {
        return result.count
     } else {
        return 0
     }
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {

    return result[row]
}

func populateVenues(completion : (result : [String]?) -> Void){
    Alamofire.request(.POST, "http://localhost:8080/ws/automobile/global/auction/latest/venues").responseJSON() {
        (_, _, jsonData, error) in

        if error == nil{
            var venues = JSON(jsonData!)

            for (k, v) in venues {

                resultOld[k] = v.arrayValue[0].stringValue

            }

            result = resultOld.values.array

            completion(result: result)
        }
        else{
            println("Error!!")
            completion(result: nil)
        }
    }
}


来源:https://stackoverflow.com/questions/28207185/why-cant-i-get-the-request-result-form-alamofire

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!