I have two UIContextualActions which should delete rows from the table after completion. I faced the following intermittent issue: If I apply this actions very fast one by one, then the first action works fine, but when I call UIContextualAction's menu for the second time it overlaps the cell. In the third time, it is not possible to call UIContextualAction's menu until tableView is scrolled. Here the short video.
Please find below the piece of code
//MARK: Swipe actions
override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = self.contextualDeleteAction(forRowAtIndexPath: indexPath)
let markAsReadAction = self.contextualMarkAsReadAction(forRowAtIndexPath: indexPath)
let markAsUnreadAction = self.contextualMarkAsUnreadAction(forRowAtIndexPath: indexPath)
let swipeConfig = UISwipeActionsConfiguration(actions: [
isArchiveModeEnabled ? markAsUnreadAction : markAsReadAction,
deleteAction
])
swipeConfig.performsFirstActionWithFullSwipe = false
return swipeConfig
}
func contextualMarkAsUnreadAction(forRowAtIndexPath indexPath: IndexPath) -> UIContextualAction {
let action = UIContextualAction(style: .normal, title: "") { _, _, completion in
let index = indexPath.row
if let article = self.getSelectedArticleByIndex(index) {
self.articlesManager.restore(article: article)
self.refreshDataSource()
self.tableView.deleteRows(at: [indexPath], with: .automatic)
self.tableView.isEditing = false //seems like it helps to fix visual bug when the action is left on blank space
completion(true)
}
}
action.backgroundColor = UIColor(patternImage: swipeActinImages.markAsUnread)
return action
}
refreshDataSource function do the following:
private func refreshDataSource() {
articles = isArchiveModeEnabled ? dataController.getArchivedArticles() : dataController.getUnreadArticles()
}
private func reloadTableData() {
if dataController.getActiveUser() != nil {
refreshDataSource()
introView?.isHidden = articles.count != 0 || isArchiveModeEnabled
tableView.isScrollEnabled = (introView?.isHidden)!
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
Appreciate any help
UPDATE
So I solved it. I've replaced UIContextualAction(style: .normal, title: "") to UIContextualAction(style: .destructive, title: "") and don't update datasource manualy anymore. Completion(true) do all needed manipulation with cell and table automaticaly.
The final code is
func contextualMarkAsUnreadAction(forRowAtIndexPath indexPath: IndexPath) -> UIContextualAction {
let action = UIContextualAction(style: .destructive, title: "") { _, _, completion in
let index = indexPath.row
if let article = self.getSelectedArticleByIndex(index) {
self.articlesManager.restore(article: article)
//self.refreshDataSource()
completion(true)
} else {
completion(false)
}
}
action.backgroundColor = UIColor(patternImage: swipeActinImages.markAsUnread)
return action
}