2016-12-27 30 views
2

有沒有辦法從ViewController(UITableViewController)外部調用alamofire發出的請求,然後用來自響應的數據填充tablewView?現在我在控制器內部創建了一個func,並在獲取數據後調用tablewView的reloadData()。但有沒有什麼辦法可以創建這樣的方法:來自外部的Alamofire請求ViewController

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

噢我的上帝,我完全忘了@escaping。在控制器端,我用這種方式調用了這個func: InsuranceServices.getContracts(completionHandler:{data in self.contracts = data self.tableView.reloadData() })並且工作。多謝! –

+3

因爲像你提到的那樣是'@ escaping',你應該避免堅持'self'。設想一種情況,你解散了視圖控制器,並且稍後請求返回 - 即使你已經解散了屏幕,自己也會留在內存中。爲了避免這種情況,你應該對自己持有「弱」的提法。我用電話編輯了我的答案...... –