【问题标题】:How to get value out of Apollo iOS Closure? / How to "wrap" a closure in a function?如何从 Apollo iOS Closure 中获取价值? / 如何在函数中“包装”闭包?
【发布时间】:2019-08-13 01:07:18
【问题描述】:

我正在使用 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 行时,我都会收到错误无法推断通用参数“查询”。

但是,当注释掉该行时,它可以正常工作,但显然该功能毫无意义。最终我想概括这个函数,这样我就可以将查询传递给它,但是我如何从这个基本闭包中获取数据呢?

本质上的问题是,我如何在函数中“包装”一个闭包?

这个函数的重点是能够在函数中获取table view section的行数:

override func tableView(_ tableView:UITableView, numberOfRowsInSection section: Int -> Int{
    return fetchQueryResults.count
}

但是,视图会在此函数运行之前加载。我认为这是因为apollo.fetch() 异步运行?

【问题讨论】:

  • 我很困惑...您的闭包将“result”作为参数,而您使用“results”
  • @Naresh 帖子中的错字,刚刚修复
  • 不确定该错误,但我建议您不要将该函数用作数据源...保留一个数组...我知道您的困惑是什么,您缺少的成分被称为一个逃逸的闭包...去这里了解它 - medium.com/@bestiosdevelope/… 这将需要一些时间来理解它,取决于您的经验...在您实现闭包后,您的 fetchQueryResults 不会返回任何内容,但它会提供一个数组作为闭包的输入,它将刷新 tableview 等...

标签: swift graphql apollo apollo-ios


【解决方案1】:

每当我添加行 myResult = result?.data 时,我都会收到错误 Generic parameter 'Query' could not be inferred。

可能修复它的几件事:

  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
}

【讨论】:

    【解决方案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)
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 2013-06-11
      • 1970-01-01
      • 1970-01-01
      • 2022-10-19
      • 2016-11-04
      • 2019-07-03
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多