Reputation: 869
I have a tableview with two sections.
var categories = ["a", "b", "c"]
var items = ["1" , "2", "3"]//will be different based on category selection
var selectedCategory: String?
Initially first section only visible. After the user selects any row in 0th section section 1 will have 3 rows and section 0 will have only selected row.
For ex. if category "b" is selected "a","c" rows should be removed and "1","2","3" rows should be added.
Now if the "b" is deselected "a","c" rows should be added and "1","2","3" rows should be removed.
//UITableViewDataSource
func numberOfSections(in tableView: UITableView) -> Int {
return selectedCategory == nil ? 1 : 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? categories.count : items.count
}
I've done this using tableView.reloadData()
. It does't show any animation. I'm trying to achieve this using the following methods
tableView.deleteRows(at: [IndexPath], with: UITableViewRowAnimation)
tableView.insertRows(at: [IndexPath], with: UITableViewRowAnimation)
I'm struggling to get indexpaths to insert and delete
Upvotes: 0
Views: 221
Reputation: 2808
You need to wrap the deleteRows
and insertRows
call in tableView.beginUpdates
and tableView.endUpdates
.
https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates?language=objc
Or use performBatchUpdates:completion:
.
Edit
Ok, let me explain some things in detail. :-)
First I think you need to modify numberOfRowsInSection
, because you said section 0 should show all categories as long as none is selected and after selecting one, it should display only that one row.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
// If no category is selected, we display all categories, otherwise only the selected one.
return selectedCategory == nil ? categories.count : 1
case 1:
return items.count
default:
return 0
}
}
Second, this is an example of how didSelectRowAt
could look like. I changed selectedCategory
to Int?
to store the index of the selected category and not its name.
As you can see, in section 0 the rows that are not the selected category are deleted, while section 1 is added completely, as it did not exist before.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedCategory == nil {
// Save index on selected category
selectedCategory = indexPath.row
// set items array
…
// Animate change
var indexPaths = [IndexPath]()
for (index, _) in categories.enumerated() {
if index != selectedCategory {
indexPaths.append(IndexPath(row: index, section: 0))
}
}
tableView.performBatchUpdates({
// delete rows from section 0
tableView.deleteRows(at: indexPaths, with: .automatic)
// insert section 1
tableView.insertSections(IndexSet(integer: 1), with: .automatic)
}, completion: nil)
}
}
Upvotes: 1
Reputation: 301
instead of reload whole tableView do this:-
tableView.beginUpdates()
tableView.deleteRows(at: [IndexPath], with: UITableViewRowAnimation.top)
tableView.insertRows(at: [IndexPath], with: UITableViewRowAnimation.top)
tableView.endUpdates()
Upvotes: 1