J'essaie de faire une demande synchrone en utilisant Alamofire
. J'ai regardé Stackoverflow et trouvé cette question: rendre synchrone une demande alamofire asynchrone .
J'ai vu que la réponse acceptée utilise completion
pour rendre Alamofire
la demande synchrone mais je ne peux pas le faire fonctionner. Voici mon code simplifié:
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)
}
Avec ce code, j'obtiens une erreur lors de la tentative de création de completion(bool value)
. L'erreur que je reçois est la suivante:
Impossible d'appeler une valeur de type non fonction 'Bool'
J'ai essayé d'utiliser de nombreux exemples en utilisant la complétion pour obtenir les valeurs de manière synchrone (car j'ai besoin de récupérer les données avant de les afficher sur une table et en même temps obtenir le nombre de lignes de cette table) sans succès.
Comment puis-je utiliser cette complétion pour obtenir une réponse synchrone?
Merci d'avance!
lorsque vous utilisez le gestionnaire d'achèvement, n'utilisez pas 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
})
ou si vous souhaitez renvoyer une valeur dans la fermeture, vous devez utiliser le gestionnaire d'achèvement pour renvoyer toute valeur ou quelque chose comme, par exemple si vous voulez renvoyer une valeur booléenne:
func loadData(completion:(number: numberRows, strArr1 : nameArray, strArr2 : ageArray, strArr3: birthdayArray) -> (Bool))
et dans le loadData
loadData( completion: { ( number, strArr1, strArr2, strArr3 ) -> (Bool) in
# code
return False
})
ou certains pensent autre chose.
J'utilise Swift 3. mais si vous voulez une autre version de Swift attention aux noms de paramètres externes et aux noms de paramètres internes, comme: @escaping (_ number: Int, _ strArr1: [String], _ strArr2: [String], _ strArr3: [String]) -> ())
si vous voulez définir des noms de paramètres externes, il suffit de déposer _
et de définir le nom des paramètres.
Notez que faire des demandes synchrones est fortement déconseillé par Apple, pour les raisons indiquées ici .
Dans cet exemple, je simplifie l'appel, si vous avez plus d'informations, telles que le contenu des cellules, je vous suggère de jeter un coup d'œil à SwiftyJSON et de renvoyer l'intégralité du blob JSON, puis de l'analyser dans les méthodes pertinentes (numberOfRows, etc. .).
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)
}
}