问题
Explanation:
I have a UITableView that is being populated from JSON. The purpose of the tableview is for the user to select individual row records and have the checkmark accessory appear as a result.
The issue is that while I can get the checkmark to appear for whichever row is selected the checkmark is applied to the row, not the record itself.
For example, if I have two rows in the tableview and I select the first row, a checkmark is applied to it, but after updating the API to remove the row and reloading the tableView the first-row disappears but the checkmark is applied to what was the second record.
This is what my didSelect method looks like:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let section = sections[indexPath.section]
structure = sections[indexPath.section].items
let theStructure = structure[indexPath.row]
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
}
This is how the structure is defined for the JSON:
struct Section {
let name : String
let items : [Portfolios]
}
struct Portfolios: Decodable {
let code: String
let maker: String
}
Essentially I need help applying the checkmark to the actual record itself not just the static row.
回答1:
The most efficient way is to add the isSelected
information to the data model (Portfolios
)
struct Portfolios : Decodable {
var isSelected = false
// other members
}
You might add also CodingKeys
to exclude isSelected
from being decoded.
In cellForRowAt
set the checkmark according to isSelected
let item = sections[indexPath.section].items[indexPath.row]
cell.accessoryType = item.isSelected ? .checkmark : .none
In didSelectRowAt
toggle isSelected
and reload the row
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
sections[indexPath.section].items[indexPath.row].isSelected.toggle()
tableView.reloadRows(at: [indexPath], with: .none)
}
回答2:
First Take an empty array of record and then add checked record to this empty array. In Tableview cellforRow check if a record is in this empty array or not. If it is present in this empty array then display checkmark else remove the checkmark.
回答3:
Tabelview cells get recycel.
You need to overwrite prepareForReuse and clear the selected state there.
override func prepareForReuse() {
super.prepareForReuse()
isSelected = false
}
As for the top answer:
Following the state in your data model is fine too as you set the state for each cel (which solves your problem).
BUT if you don't need the state other then for deleting entries, then storing the state is pointless. Thing is, all elements in your data model have the state of not selected. So why store an identical information? It is a redundant information that cost you memory for each element.
In this case is overriding the prepareForReuse function the best approach.
来源:https://stackoverflow.com/questions/57519734/how-to-apply-tableview-cell-accessory-to-a-tableview-record