2016-10-10 5 views
7

Я пытаюсь выполнить синхронный запрос, используя Alamofire. Я посмотрел Stackoverflow и нашел этот вопрос: making an asynchronous alamofire request synchronous.Как сделать синхронный запрос с помощью 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»

Я попытался использовать много примеров использования завершения, чтобы получить значения синхронно (т.к. Мне нужно получить данные, прежде чем показывать их на столе и в то же время получить количество строк этой таблицы) без успеха.

Как использовать это завершение для получения синхронного ответа?

Заранее благодарен!

+0

Я бы порекомендовал вам реализовать свой собственный метод. Apple сильно обескуражила синхронные сетевые вызовы. Взгляните на это: http://stackoverflow.com/questions/31557688/synchronous-url-request-on-swift-2 – FredLoh

+0

https://github.com/Alamofire/Alamofire/issues/1147, вы должны увидеть этот блог. Надеюсь, это поможет вам. –

+0

Кажется, вы не понимаете, как работают асинхронные методы, особенно с обратными вызовами завершения. Вместо того, чтобы форсировать синхронные вызовы, инвестируйте эти усилия в понимание асинхронного программирования. – vikingosegundo

ответ

1

при использовании завершение обработчик не использовать возврат.

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 
}) 

или некоторые думают еще.

Я использую скор 3. но если вы хотите другую версию быстра осторожной о внешних параметрах именах и именах внутренних параметров, такие как: @escaping (_ number: Int, _ strArr1: [String], _ strArr2: [String], _ strArr3: [String]) ->())

, если вы хотите установить имена внешних параметров, нужно просто отбросить _ и установить имя параметры.

+0

Большое спасибо! Ты дал мне ключ к решению моей проблемы! :) –

+0

Вы поняли. Я так рад, что смогу помочь. ;-) –

0

Обратите внимание, что использование синхронных запросов категорически не одобряется 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) 

    } 
} 
+0

Функция сна также не будет блокировать пользовательский интерфейс? –

+0

Будет, я использую его для имитации синхронного вызова.Синхронный сетевой запрос блокирует основной поток, поэтому он сильно обескуражен. Если вы не делаете это в отдельном потоке (который даст вам другие проблемы, такие как неспособность отменить запрос и т. Д.), В этот момент вы также можете сделать его асинхронным. – FredLoh

+0

Проблема заключается в том, что, поскольку мне нужно получить количество строк таблицы перед отображением таблицы, мне нужно сделать ее синхронной (или, по крайней мере, это единственный способ, на который я могу сосредоточиться). Если я сделаю это асинхронно, я получаю, что в таблице будет 0 строк. –