In my project I am using a UITableView with a UITableViewDiffableDataSource. I love how easy it is to get up and running with very little boiler plate code and all the free animations. It's a great API!
In my project I have implemented a trailing swipe action AND a context menu action. The action allows the user to mark the message read or unread similar to the native Mail app in iOS.
I had assumed that this could be accomplished using the following code:
I assumed the method reloadItems(_:) was intended to replace using reloadRows(at:with:) since that method is not available to you when you are using UITableViewDiffableDataSource.
So far I have run into this error, usually when I am using a struct for my model object with inferred Hashable conformance OR even sometimes with a class, but I can't see to put my finger on it.
Once I am past getting that error, I am noticing that the method doesn't seem to do what I want. The dataSource holds onto the old object with the old value for isRead. So when the cell is reloading it's view, it doesn't change at all, because it receives the old value for the isRead property. That lead me to this workaround:
The DispatchQueue.main.async was a last ditch effort to get it working and it finally did, but this definitely does not feel right.
If someone has been able to figure it out. I would appreciate some help in understanding what/how reloadItems(_:) is intended to work.
I have a feeling it all comes down to Hashable but I am not sure exactly what. Thanks!
In my project I have implemented a trailing swipe action AND a context menu action. The action allows the user to mark the message read or unread similar to the native Mail app in iOS.
I had assumed that this could be accomplished using the following code:
Code Block Swift enum Section: CaseIterable { case main } struct Item: Hashable { var isRead: Bool let identifier = UUID() /* Hashable */ static func == (lhs: Item, rhs: Item) -> Bool { return lhs.identifier == rhs.identifier } func hash(into hasher: inout Hasher) { hasher.combine(identifier) } } class ViewController: UITableViewController { var dataSource: UITableViewDiffableDataSource<Section, Item>! ... func markItemRead(_ item: Item) { var snapshot = dataSource.snapshot() var updatedItem = item updatedItem.isRead = true snapshot.reloadItems(updatedItem) self.dataSource.apply(snapshot) } }
I assumed the method reloadItems(_:) was intended to replace using reloadRows(at:with:) since that method is not available to you when you are using UITableViewDiffableDataSource.
So far I have run into this error, usually when I am using a struct for my model object with inferred Hashable conformance OR even sometimes with a class, but I can't see to put my finger on it.
Once I am past getting that error, I am noticing that the method doesn't seem to do what I want. The dataSource holds onto the old object with the old value for isRead. So when the cell is reloading it's view, it doesn't change at all, because it receives the old value for the isRead property. That lead me to this workaround:
Code Block Swift func markItemRead(_ item: Item) { let oldSnapshot = dataSource.snapshot() let oldItems = oldSnapshot.itemIdentifiers(inSection: .main) let updatedItems: [Item] = oldItems.map { if $0 == item { var updatedItem = $0 updatedItem.isRead = true return updatedItem } return $0 } var snapshot = NSDiffableDataSourceSnapshot<Section, ConversationsController.Conversation>() snapshot.appendSections([.main]) snapshot.appendItems(updatedItems, toSection: .main) dataSource.apply(snapshot) DispatchQueue.main.async { var snapshot = self.dataSource.snapshot() snapshot.reloadItems([item]) self.dataSource.apply(snapshot) self.refreshBadge() } }
The DispatchQueue.main.async was a last ditch effort to get it working and it finally did, but this definitely does not feel right.
If someone has been able to figure it out. I would appreciate some help in understanding what/how reloadItems(_:) is intended to work.
I have a feeling it all comes down to Hashable but I am not sure exactly what. Thanks!