2016-10-10 16 views
7

Alamofireを使用して同期要求を実行しようとしています。私はStackoverflowを見て、この質問が見つかりました:making an asynchronous alamofire request synchronousAlamofireを使用して同期リクエストを作成するにはどうすればよいですか?

completionを使用してAlamofireリクエストを同期させることができますが、動作させることはできません。 completion(bool value)をしようとしたとき、私はエラーを取得しています。このコードで

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

:これは私の単純化されたコードです。私は取得していますエラーは以下の通りです:

はので(私は同期の値を取得するために完了を使用した例の多くを使用して試してみました「ブール」

を非機能型の値を呼び出すことはできませんテーブルに表示する前にデータを取得する必要がありますが、同時にそのテーブルの行数を取得する必要があります)。

どうすれば同期応答を得ることができますか?

ありがとうございます!

+0

独自の方法を実装することをお勧めします。アップルは、同期ネットワークコールを大いに妨げている。これを見てください: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

スリープ機能もUIをブロックしませんか? –

+0

これは、同期呼び出しをシミュレートするために使用します。同期ネットワーク要求はメインスレッドをブロックします。なぜなら、これは非常に推奨されていません。別のスレッドで(リクエストをキャンセルできないなどの他の問題が発生する)、それを非同期にすることができます。 – FredLoh

+0

問題は、テーブルが表示される前にテーブルの行数を取得する必要があるため、同期させる必要があることです(少なくとも、私が焦点を当てることができる唯一の方法です)。私は非同期にそれを行う場合、私はテーブルが0行を持つことがわかります。 –

関連する問題