Mutation and update cache
Now let's do the integration part. Open Todo/TodoVC.swift
and add the following code at the bottom of the file:
// Toggle Todos to Cloudprivate func toggleTodosMutationCloud(checked: Bool, index: Int!){apollo.perform(mutation: ToggleTodoMutation(id: filteredTodos[index].id, isCompleted: checked)) { (result, error) inguard let data = result?.data else { return }if data.updateTodos?.affectedRows == 1 { return } else {// With some error - revert to original state : Watcher will update the table anyways on local cache updateself.toggleTodosMutationLocal(id: index, checked: checked)}}}
Lets also, add the function for adding the mutation to the local cache,
// Toggle Todos local cacheprivate func toggleTodosMutationLocal(id: Int, checked: Bool){_ = apollo.store.withinReadWriteTransaction{ transaction inlet query = GetMyTodosQuery()try transaction.update(query: query) { (data: inout GetMyTodosQuery.Data) inlet todos = data.todosguard let index = todos.firstIndex(where: {$0.id == id}) else {return}data.todos[index].isCompleted = checked_ = self.apollo.store.load(query: query).andThen({ (data) in// Watch your data in local cache// dump(data.data?.resultMap)// Look for errors// dump(data.errors)})}}}
We need to modify our todoQueryCloud
to todoQueryWacther
to watch for changes in a particular query on the local cache. To make sure, it is initialized properly and discarded we need to update our viewWillAppear
and viewWillDisapper
:
// Todo Query Watcher from local cache- private func todoQueryCloud(){- apollo.fetch(query: GetMyTodosQuery()){ (result, error) in+ private func todoQueryWatcher() -> GraphQLQueryWatcher<GetMyTodosQuery>{+ return apollo.watch(query: GetMyTodosQuery(), resultHandler: {(result, error) inif ((error) != nil) {if SessionManager.shared.logout() {self.performSegue(withIdentifier: "loginVC", sender: self)}return}guard let data = result?.data else { return }self.todos = data.todos- self.filteredTodos = data.todos+ self.filteredTodos = self.getFilteredTodos(segmentIndex: self.todoFilter.selectedSegmentIndex)self.setupUI()self.todoTable.reloadData()})}
override func viewWillAppear(_ animated: Bool) {if( SessionManager.shared.credentials?.idToken! != nil ) {apollo = NetworkManager.shared.apolloClient// Initialize a Watcher to check for updates- todoQueryCloud()+ todoWatcher = todoQueryWatcher()}}+ override func viewWillDisappear(_ animated: Bool) {+ todoWatcher?.cancel()+ }
todoWatcher
will update the todos
and filteredTodos
when there is any update in the cache.
We already have the onChange handler checkBox
for the tablecell. Let's update the function to make a mutation.
// OnClick of Checkboxfunc checkBox(checked: Bool, index: Int!) {// Optimistic update & Change UItoggleTodosMutationLocal(id: filteredTodos[index].id, checked: checked)let index = self.todos.firstIndex{$0.id == filteredTodos[index].id}!todos[index].isCompleted = checkedfilteredTodos[index].isCompleted = checkedtodoTable.reloadRows(at: [IndexPath(row: index, section: 0)], with: UITableView.RowAnimation.automatic)// Update NetworktoggleTodosMutationCloud(checked: checked, index: index)}
The above code will just make a mutation, updating the todo's isCompleted property in the local cache. After updating the cache, we update the UI to make this change visible. And then call the toggleTodosMutationCloud
to update the cloud. If there was any error, in updating the cloud, it will inturn update the local cache and through watcher, it will automatically revert to the original state.
- Build apps and APIs 10x faster
- Built-in authorization and caching
- 8x more performant than hand-rolled APIs