我正在尝试使用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'的值
我尝试使用很多使用完成的示例来同步获取值(因为我需要先检索数据才能在表上显示它,同时获取该表的行数)但没有成功。
如何使用该完成功能获得同步响应?
提前致谢!
答案 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)
}
}