2016-12-27 19 views
2

ViewController(UITableViewController)の外部からalamofireによるリクエストを呼び出し、responseからのデータをtablewViewに取り込む方法はありますか?今私はコントローラ内でfuncを作成し、データをフェッチした後にtablewViewのreloadData()を呼び出します。しかし、このようなメソッドを作成する方法はありますか:外部からのAlamofireリクエスト

class InsuranceServices { 

    class func getContracts(table : UITableView) -> [Contract] { 
     var contracts = [Contract]() 
     let headers : HTTPHeaders = [ 
      "Content-Type":"application/json" 
     ] 
     let params : Parameters = [String:Any]() 

     Alamofire.request("http://test:9090/testService/getContracts", method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).validate().responseJSON(completionHandler: {response -> Void in 

      switch response.result { 
      case .success(let value): 
       let json = JSON(value) 
       for data in json["data"].arrayValue { 
        let contract = Contract(json: data) 
        print(contract.fullName!) 
        contracts.append(contract) 
       } 
      case .failure(let error): 
       print(error) 
      } 
      table.reloadData() 
     }) 
     return contracts 
    } 

} 

このメソッドは私のために働いていません。多分別の方法がありますか?私はコントローラ内の作成サービスメソッドが間違っていると思います。

答えて

5

ViewControllerAlamofireの間に明確な区別があります。 これを達成する方法は、あなたが書いたのと似ていますが、UITableViewを取る代わりに、関数は[Contract]を受け取る完了ブロックを取る必要があります。

は、それはこのような何かを見ることができます:

class func getContracts(completion: @escaping ([Contract])→Void) { 
    //... 
    Alamofire.request(...).responseJSON(completionHandler: {response -> Void in 

     switch response.result { 

     case .success(let value): 
      let json = JSON(value) 
      var contracts = [Contract]() 
      for data in json["data"].arrayValue { 
       let contract = Contract(json: data) 
       contracts.append(contract)      
      } 
      completion(contracts) 

     case .failure(let error): 
      print(error) 
      completion([]) 
     } 
    }) 
} 

もう一つは、あなたが関数の戻り値の(Contractのあなたのケースの配列に)要求の結果を返すことができないということです。 Alamofireは要求を非同期的に呼び出すので、関数の戻りよりもずっと後に終了します。そのため、私が書いた関数の署名が何も返されないことがわかります。代わりに、要求が準備されデータが利用可能なときにcompletionクロージャを呼び出します。

にする必要があります。失敗した場合でもcompletionと呼んでください。そうでない場合は(あなたの場合、あなたのビューコントローラでの)呼び出し側は永遠にそれが失敗を知らないリクエストをお待ちしています....

あなたは、あなたがselfでメモリリークが発生していないことを確認すること、そのような関数を呼び出すことができます:

InsuranceServices.getContracts(completionHandler: { [weak self] data in 
    self?.contracts = data 
    self?.tableView.reloadData() 
}) 
+0

私の神、私は@エスケープについて完全に忘れています。コントローラ側では、次のようにこのfuncを呼び出しました。 InsuranceServices.getContracts(completionHandler:{ のデータ、self.contracts = data のself.tableView.reloadData() })これが機能しました。ありがとう! –

+3

あなたが言及したように '@エスケープ 'なので、あなたは' self'を保持しないでください。 View Controllerを却下した後、リクエストが返ってくる状況を想像してみてください。画面を閉じたとしても、selfはメモリに残ります。それを避けるためには、自己への「弱い」参照を保持する必要があります。私は電話で自分の答えを編集しました... –

関連する問題