Как сделать синхронный запрос с помощью Alamofire?
Я пытаюсь сделать синхронный запрос, используя Alamofire
. Я посмотрел на StackOverflow и нашел этот вопрос: создание асинхронного запроса Alamofire синхронно.
Я видел, что принятый ответ использует 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 ответов
при использовании обработчика завершения не используйте return.
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
loadData( completion: { ( number, strArr1, strArr2, strArr3 ) -> (Bool) in
# code
return False
})
или некоторые думают иначе.
Я использую swift 3. но если вы хотите другую версию swift, будьте осторожны с внешними именами параметров и внутренними именами параметров, например: @escaping (_ number: Int, _ strArr1: [String], _ strArr2: [String], _ strArr3: [String]) -> ())
если вы хотите установить имена внешних параметров, просто нужно капля _
и введите имя для параметров.
обратите внимание, что выполнение синхронных запросов очень не рекомендуется Apple по причинам, отмеченным здесь.
в этом примере я упрощаю вызов, если у вас есть дополнительная информация, такая как содержимое ячеек, я предлагаю вам взглянуть на 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)
}
}