Автоматические обновления пользовательского интерфейса с Apollo в Swift не работает
У меня есть следующая настройка для небольшого приложения Apollo для iOS, где я отображаю список конференций в виде таблицы и хочу добавить конференцию в список:
GraphQL:
query AllConferences {
allConferences {
...ConferenceDetails
}
}
mutation CreateConference($name: String!, $city: String!, $year: String!) {
createConference(name: $name, city: $city, year: $year) {
...ConferenceDetails
}
}
fragment ConferenceDetails on Conference {
id
name
city
year
attendees {
...AttendeeDetails
}
}
fragment AttendeeDetails on Attendee {
id
name
conferences {
id
}
}
ConferencesTableViewController:
class ConferencesTableViewController: UITableViewController {
var allConferencesWatcher: GraphQLQueryWatcher<AllConferencesQuery>?
var conferences: [ConferenceDetails] = [] {
didSet {
tableView.reloadData()
}
}
deinit {
allConferencesWatcher?.cancel()
}
override func viewDidLoad() {
super.viewDidLoad()
allConferencesWatcher = apollo.watch(query: AllConferencesQuery()) { result, error in
print("Updating conferences: ", result?.data?.allConferences)
guard let conferences = result?.data?.allConferences else {
return
}
self.conferences = conferences.map { $0.fragments.conferenceDetails }
}
}
// ...
// standard implementation of UITableViewDelegate
// ...
}
AddConferenceViewController:
class AddConferenceViewController: UIViewController {
// ... IBOutlets
@IBAction func saveButtonPressed() {
let name = nameTextField.text!
let city = cityTextField.text!
let year = yearTextField.text!
apollo.perform(mutation: CreateConferenceMutation(name: name, city: city, year: year)) { result, error in
if let _ = result?.data?.createConference {
self.presentingViewController?.dismiss(animated: true)
}
}
}
}
Я также реализовал cacheKeyForObject
в AppDelegate вот так:
apollo.cacheKeyForObject = { $0["id"] }
Мой вопрос заключается в том, можно ли воспользоваться автоматическими обновлениями пользовательского интерфейса с помощью этой настройки? В настоящее время, когда CreateConferenceMutation
выполняется, представление таблицы не обновляется. Я что-то упускаю или нарушаю ограничение, упомянутое в документации:
В некоторых случаях, просто используя
cacheKeyFromObject
недостаточно для корректного обновления пользовательского интерфейса приложения. Например, если вы хотите добавить что-то в список объектов без повторной загрузки всего списка или если есть какие-то объекты, которым вы не можете назначить идентификатор объекта, Apollo не сможет автоматически обновить существующие запросы для вас.
1 ответ
Это действительно ограничение автоматических обновлений пользовательского интерфейса. Хотя Аполлон использует cacheKeyFromObject
чтобы сопоставить объекты по идентификатору, и это охватывает многие распространенные случаи, он не может автоматически обновлять списки объектов.
В вашей схеме Аполлон не может знать, что недавно добавленная конференция должна быть добавлена к allConferences
список. Все, что он знает, это то, что allConferences
возвращает список объектов конференции, но они могут быть произвольно выбраны и упорядочены.
Поэтому в подобных случаях вам придется самостоятельно повторно запросить запрос с сервера или изменить результат мутации, чтобы включить обновленный список.
Другой вариант - вручную добавить новую конференцию в список в хранилище клиентов. Для этого в следующую версию Apollo iOS будет включена опция ручного обновления, аналогичная updateQueries
в клиенте Apollo JavaScript.