Автоматические обновления пользовательского интерфейса с 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.

Другие вопросы по тегам