我正在使用Apollo iOS来获取GraphQL查询。我想将apollo.fetch()
查询闭包移动到类中的单独函数中。该类将包含对apollo客户端的静态引用以及执行GraphQL突变和查询的功能。
我正在尝试以下操作:
static func fetchQueryResults() -> CountriesQuery.Data.Country?{
var myResult: CountriesQuery.Data.Country?
myResult = nil
apollo.fetch(query: countriesQuery) { (result, error) in
print(result?.data)
myResult = result?.data //this line causes error
}
return myResult
}
每当我添加行myResult = result?.data
时,都会出现错误无法推断出通用参数“查询”。
但是,当注释掉该行时,它可以正常工作,但显然该功能没有意义。最终,我想对该函数进行一般化,以便可以将查询传递给它,但是如何从该基本闭包中获取数据?
本质上,问题是,如何在函数中“包装”闭包?
此函数的重点是能够获取该函数中表视图部分的行数:
override func tableView(_ tableView:UITableView, numberOfRowsInSection section: Int -> Int{
return fetchQueryResults.count
}
但是,视图会在此函数运行之前加载。我认为这是因为apollo.fetch()
正在异步运行吗?
答案 0 :(得分:2)
当前,我正在使用最新版本的Apollo iOS版本0.16.0 https://github.com/apollographql/apollo-ios
有一些与版本低于0.13.0相关的更改,您可以查看0.13.0 release notes-不要使用(result, error)
,因为它们已经从可为空的参数元组切换为结果。
尝试使用类似这样的内容:
Apollo.shared.client.fetch(query: GetProductQuery(id: id)) { results in
do {
if let gqlErrors = try results.get().errors {
if(!gqlErrors.isEmpty) {
apiResponseError.message = gqlErrors[0].message
publishSubject.onError(apiResponseError)
}
return
}
guard let gplResult = try results.get().data?.getProduct else {
apiResponseError.message = "Error getting results"
publishSubject.onError(apiResponseError)
return
}
publishSubject.onNext(gplResult)
} catch let errorException {
apiResponseError.message = errorException.localizedDescription
publishSubject.onError(apiResponseError)
}
}
答案 1 :(得分:1)
每当我添加myResult = result?.data行时,我都会得到错误,无法推断出通用参数“查询”。
可能可以修复的几件事:
将import Apollo
添加到该Swift文件。您可能已经拥有了,但是如果您使用静态实用程序类创建apollo
实例,则可能会实现。
将, error
放到闭包中,使其仅为{ result in
。我认为很多教程中都使用了较旧的语法,但是error
现在是result
本身的一部分。
但是,视图会在此函数运行之前加载。我认为这是因为apollo.fetch()正在异步运行?
默认情况下,它运行DispatchQueue.main
,但是您可以使用fetch()
函数调用并填写要在其上运行的DispatchQueue(即,在xCode中键入“ fetch”时,自动完成功能将实际上将其显示为2个不同的func签名:一个隐藏默认参数的所有参数,第二个可以显式填写每个参数。)
通常,在表视图中异步加载数据的一种好模式是:
var countries: [Country] = [Country]()
func viewDidLoad() {
super.viewDidLoad()
apollo.fetch(query: countriesQuery) { result in
self.countries.removeAll() // clear the old data
// unpack each Country from result
// add to countries array
self.tableView.reloadData() // tell the table view to refresh
}
}
override func tableView(_ tableView:UITableView, numberOfRowsInSection section: Int -> Int{
return countries.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let country = countries[indexPath.row]
let yourCell: YourCell = tableView.dequeueReusableCell(withIdentifier: "yourCellKey", for: indexPath) as! YourCell
yourCell.setCountry(country)
return yourCell
}