如何从Apollo iOS Closure中获得价值? /如何在函数中“包装”闭包?

时间:2019-03-22 04:30:27

标签: swift graphql apollo apollo-ios

我正在使用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()正在异步运行吗?

2 个答案:

答案 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行时,我都会得到错误,无法推断出通用参数“查询”。

可能可以修复的几件事:

  1. import Apollo添加到该Swift文件。您可能已经拥有了,但是如果您使用静态实用程序类创建apollo实例,则可能会实现。

  2. , 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
}