来自ViewController外部的Alamofire请求

时间:2016-12-27 20:01:58

标签: ios swift rest alamofire

有没有办法从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
    }

}

这种方法对我不起作用。也许有另一种方式?我认为控制器内部的创建服务方法是不正确的。

1 个答案:

答案 0 :(得分: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() 
})