2016-12-27 42 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'。设想一种情况,你解散了视图控制器,并且稍后请求返回 - 即使你已经解散了屏幕,自己也会留在内存中。为了避免这种情况,你应该对自己持有“弱”的提法。我用电话编辑了我的答案...... –