SDK Setup Guides
...
Quick Tips for Swift
Animating UITableView with the Observe API
the ditto observe callback will fire for any changes to the underlying query these changes can happen from your own device or a replication there are two parameters for the callback handler, the current snapshot of documents and an event that gives a bit more information about how snapshots evolve after subsequent calls let livequery = mycollection find("store id == 'abc123'") observelocal { \[weak self] documents, event in print("current snapshot of documents", documents) print("event information", event) } the event parameter gives you information about how the live query has evolved from callback fire it can tell you which document indices were inserted, updated, moved, or removed the following example below shows a common pattern to parse the event parameter and apply tableview\ performbatchupdates using the indexes the following code snippet assumes that you only have one uitableview section import uikit import dittoswift class viewcontroller uiviewcontroller { var livequery dittolivequery? @iboutlet weak var tableview! var documents \[dittodocument] = \[] override func viewdidload(){ super viewdidload(); tableview\ datasource = self livequery = collection find("store id == 'abc123'") observelocal { \[weak self] docs, event in guard let `self` = self else { return } switch event { case update(let changes) guard changes insertions count > 0 || changes deletions count > 0 || changes updates count > 0 || changes moves count > 0 else { return } dispatchqueue main async { self tableview\ beginupdates() self tableview\ performbatchupdates({ let deletionindexpaths = changes deletions map { idx > indexpath in return indexpath(row idx, section 0) } self tableview\ deleterows(at deletionindexpaths, with automatic) let insertionindexpaths = changes insertions map { idx > indexpath in return indexpath(row idx, section 0) } self tableview\ insertrows(at insertionindexpaths, with automatic) let updateindexpaths = changes updates map { idx > indexpath in return indexpath(row idx, section 0) } self tableview\ reloadrows(at updateindexpaths, with automatic) for move in changes moves { let from = indexpath(row move from, section 0) let to = indexpath(row move to, section 0) self tableview\ moverow(at from, to to) } }) { in } // set the tasks array backing the uitableview to the new documents self tasks = docs self tableview\ endupdates() } case initial // set the tasks array backing the uitableview to the new documents self tasks = docs dispatchqueue main async { self tableview\ reloaddata() } default break } } } } extension viewcontroller uitableviewdatasource { func tableview( tableview uitableview, numberofrowsinsection section int) > int { return documents count } func tableview( tableview uitableview, cellforrowat indexpath indexpath) > uitableviewcell { let document = documents\[indexpath row] let cell = tableview\ dequeuereusablecell(withidentifier "cell") ?? uitableviewcell(style default, reuseidentifier "cell") cell textlabel? text = document\["text"] stringvalue return cell } }