Как извлечь выгоду из Apollo iOS Closure? Как "обернуть" замыкание в функцию?

Я использую 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 ответов

В настоящее время я использую Apollo iOS версии 0.16.0, которая является последней версией https://github.com/apollographql/apollo-ios

Есть несколько изменений, связанных с версией ниже 0.13.0, вы можете ознакомиться с примечаниями к выпуску 0.13.0 - Не используйте(result, error) потому что они переключились с кортежа параметров, допускающих значение NULL, на результат.

Попробуйте использовать что-то вроде этого:

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)
        }

    }

Всякий раз, когда я добавляю строку myResult = result?.Data, я получаю сообщение об ошибке. Общий параметр "Запрос" не может быть выведен.

Пара вещей, которые могут это исправить:

  1. добавлять import Apolloв этот файл Swift. Вероятно, он у вас уже есть, но если вы создадите свойapollo экземпляр с использованием статического служебного класса, это могло быть возможно.

  2. Отбросьте , error в вашем закрытии, так что это просто { result in. Я думаю, что это старый синтаксис, который есть во многих учебных пособиях, ноerror теперь является частью result сам.

Однако представление загружается до запуска этой функции. Я думаю, это потому, что apollo.fetch() работает асинхронно?

По умолчанию запускается DispatchQueue.main, но вы можете использовать fetch() вызов функции и укажите, на каком DispatchQueue вы хотите, чтобы он запускался (например, когда вы вводите "выборку" в xCode, автозаполнение фактически покажет его как две разные сигнатуры функции: одна, которая скрывает все параметры со значениями по умолчанию, а вторая, где вы можете явно указать каждый параметр).

В общем, хороший образец для асинхронной загрузки данных в табличном представлении:

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
}
Другие вопросы по тегам