如何使用Alamofire发出同步请求?

时间:2016-10-10 14:48:53

标签: ios swift alamofire synchronous

我正在尝试使用Alamofire执行同步请求。我查看了Stackoverflow,发现了这个问题:making an asynchronous alamofire request synchronous

我看到接受的答案使用completion来使Alamofire请求同步,但我无法使其工作。这是我的简化代码:

func loadData(completion: (Bool)) -> (Int, [String], [String], [String]){

    Alamofire.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in

        switch(response.result) {
        case .success(_):
            if let JSON = response.result.value as! [[String : AnyObject]]!{
                 //Here I retrieve the data
            }

            completion(true)
            break

        case .failure(_):
            print("Error")
            completion(false)
            break  
        }
   }

   return (numberRows, nameArray, ageArray, birthdayArray)
}

使用此代码时,我在尝试制作completion(bool value)时收到错误消息。我得到的错误如下:

  

无法调用非函数类型'Bool'的值

我尝试使用很多使用完成的示例来同步获取值(因为我需要先检索数据才能在表上显示它,同时获取该表的行数)但没有成功。

如何使用该完成功能获得同步响应?

提前致谢!

2 个答案:

答案 0 :(得分:3)

使用完成处理程序时请勿使用return。

d3.selectAll("button").on("click", function() {
     if (this.id == "unvaccinated")
         status = 0;
     else if (this.id == "vaccinated") {
         status = 1;
     } else {
         numOfPartner = this.id;
     }
     svg.selectAll("image2")
         .data(([data[1]]))
         .enter()
         .append("svg:image")
         .attr("x", function(d) {
             return widthScale(data[1][numOfPartner]) - 45;
         })
         .attr('y', '-40')
         .attr("height", 200)
         .attr("width", 115)
         .attr("xlink:href", "link to blue woman");

     rects
         .data(data)
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("width", function(d) {
             return widthScale(data[status][numOfPartner]);
         });

     svg.selectAll("text")
         .data(([data[0]]))
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("x", function(d) {
             return widthScale(data[status][numOfPartner])
         })
         .text(function(d) {
             return data[status][numOfPartner] + " %"
         });

     svg.selectAll("image")
         .data(([data[0]]))
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("x", function(d) {
             //get correct number     
             return widthScale(data[status][numOfPartner]) - 45;
         });


     svg.selectAll("image2")
         .data(([data[1]]))
         .transition()
         .duration(1000)
         .ease("linear")
         .attr("x", function(d) {
             //get correct number     
             return widthScale(data[1][numOfPartner]) - 45;
         });

     });

});

或者如果你想在闭包中返回任何值,你必须使用完成处理程序来返回任何值或某些东西,例如,如果你想返回布尔值:

func loadData(completion: @escaping (_ number: Int, _ strArr1: [String], _ strArr2: [String], _ strArr3: [String]) -> ()){

  Alamofire.request(url!, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil).responseJSON { response in

    switch(response.result) {
    case .success(_):
        if let JSON = response.result.value as! [[String : AnyObject]]!{
            //Here I retrieve the data
        }
        completion(number: numberRows, strArr1 : nameArray, strArr2 : ageArray, strArr3: birthdayArray)
        break

    case .failure(_):
        print("Error")
        completion(number: numberRows, strArr1 : nameArray, strArr2 : ageArray, strArr3: birthdayArray)
        break
    }
  }
}

loadData (completion: { (number, strArr1, strArr2, strArr3) in
    // do it
    // for exapmple
    self.number = number
    self.strArr1 = strArr1
    // and so on

})

func loadData(completion:(number: numberRows, strArr1 : nameArray, strArr2 : ageArray, strArr3: birthdayArray) -> (Bool))

loadData

或者其他人想。

我使用swift 3.但是如果你想要另外一个版本的swift小心外部参数名称和内部参数名称,例如:loadData( completion: { ( number, strArr1, strArr2, strArr3 ) -> (Bool) in # code return False })

如果要设置外部参数名称,只需要删除@escaping (_ number: Int, _ strArr1: [String], _ strArr2: [String], _ strArr3: [String]) -> ())并设置参数名称。

答案 1 :(得分:1)

请注意,Apple强烈建议不要发出同步请求,原因是here

在这个例子中我简化了调用,如果你有更多的信息,比如单元格的内容,我建议你看一下SwiftyJSON并返回整个JSON Blob,然后用相关的方法解析它( numberOfRows等。)。

class TableViewJSONAsynchCalls: UIViewController, UITableViewDelegate, UITableViewDataSource {
    var tableView = UITableView()
    var numberOfRows = 0;

    override func viewDidLoad() {
        loadData { (didCompleteRequest) in
            if (didCompleteRequest) {
                tableView.delegate = self
                tableView.dataSource = self
                tableView.reloadData()
            } else {
                // Handle error if data was not loaded correctly
            }
        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return numberOfRows;
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("selected")
    }

    func loadData(completion: (Bool) -> Void) {
        // Make asynchronous call using alamofire
        // This simulates you parsing the JSON and setting the relevant variables, 
        // personally I would recommend you return a JSON blob and then 
        // parse it in the relevant methods.
        sleep(2)
        // If call is successful
        self.numberOfRows = 10
        completion(true)

    }
}