有没有办法从ViewController(UITableViewController)外部调用alamofire的请求,然后用来自响应的数据填充tablewView?现在我在控制器内创建了一个func,在获取数据之后只需调用tablewView的reloadData()。但有没有办法创建这样的方法:
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
}
}
这种方法对我不起作用。也许有另一种方式?我认为控制器内部的创建服务方法是不正确的。
答案 0 :(得分:5)
您应该在ViewController
和Alamofire
之间保持明显的分离。
实现这一点的方法与您编写的内容类似,但是您的函数应该采用接收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()
})