If you want dynamics table you should work with data models and update them every time you want to change the data showed on the table view.
What I mean?
A good approach is to have for every row in the table view a model with the data that you want to show in that row (CellModel).
So, in your table view controller you are going to have a list of CellModels:
private var cellModels = [ CellModel ]()
Create cell models on your view did load function and implemente UITableViewDatasource functions:
// MARK: - UITableViewDatasource implementation.
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.cellModels.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellModel = self.cellModels[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: kTableViewCellIdentifier, for: indexPath)
cell.textLabel?.text = cellModel.cellData.menuDataTitle
return cell
}
Now It's time to work with the CellModel class: this class represents the data that you are going to show in one row.
In every row of this simple tutorial you are showing a string with a title, but imagine that you want to show a title, subtitle and an image, in this case It's convenient to create a class in order to represents the data that you are going to show on the row.
I named It as "CellData":
class CellData {
// MARK: - Vars.
private(set) var menuDataTitle: String
// MARK: - Initialization.
init(title: String) {
self.menuDataTitle = title
}
}
On the other hand for each row you have a menu to show, so It's convenient to have a model that represents that menu that you are going to show. I named It as "CellContextMenuData":
class CellContextMenuData {
// MARK: - Vars.
private(set) var contextMenuTitle: String
private(set) var contextMenuActions = [ UIAction ]()
// MARK: - Initialization.
init(title: String) {
self.contextMenuTitle = title
}
}
This model have a title and actions to show on the menus:
// MARK: - UITableViewDelegate.
override func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let cellModel = self.cellModels[indexPath.row]
let cellContextMenuData = cellModel.cellContextMenuData
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { suggestedActions in
return UIMenu(title: cellContextMenuData.contextMenuTitle, children: cellContextMenuData.contextMenuActions)
}
}
So, every time that you want to change the menu title (or Actions):
1 - Retrieve the cell model that represents the row that you want to change.
2 - Change the title of the CellContextMenuData.
3 - Reload the tableview.
Example:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Timer to change our data.
Timer.scheduledTimer(withTimeInterval: 5.0, repeats: false) { [weak self] timer in
let cellModel = self?.cellModels[3]
let cellContextMenuData = cellModel?.cellContextMenuData
cellContextMenuData?.contextMenuUpdate(title: "Expired")
cellContextMenuData?.contextMenuSetActionsShareUpdateDelete()
self?.tableView.reloadData()
}
}
I created an example, feel free to use/see it: https://bitbucket.org/gastonmontes/contextmenuexample