[swift-users] Issues with UITableView*
Ole Begemann
ole at oleb.net
Mon Sep 12 17:41:35 CDT 2016
> Hmm - interesting to know. Unfortunately, if I do that, then I get
> NO indication of selection when I click on ANY row. Perhaps I need
> to make some other changes to account for the change in how I get the
> cell?
You also need to store your cells' selection state someplace outside of
the cells themselves. The cells should not be the "source of truth" for
the selection state. Otherwise, when you scroll a cell off screen and
then scroll it back, it will lose its state.
So you should store the selection state of each table row somewhere
alongside your `locationList` array. Maybe as an array of pairs like this:
var locationList: [(location: LocationObject, selected: Bool)] = [
(
location: LocationObject(name: "name-1", address: "addr-1",
phone: "phone-1", latitude: 40.0, longitude: -80.1),
selected: false
),
(
location: LocationObject(name: "name-2", address: "addr-2",
phone: "phone-2", latitude: 40.0, longitude: -80.1),
selected: false
)
]
There may be better ways to structure your model data, but this should
suffice for now.
Then:
1. In `tableView(_:cellForRowAtIndexPath:)`, use the current value of
`item.selected` to configure the cell's selection state:
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell =
tableView.dequeueReusableCellWithIdentifier("resultCell", forIndexPath:
indexPath) as! ExistingLocationTableViewCell
let item = locationList[indexPath.row]
cell.nameLabel.text = item.location.name
cell.locationLabel.text = item.location.address
cell.accessoryType = item.selected ? .Checkmark : .None
return cell
}
One note: on iOS, the convention for table views is that rows should
generally not remain selected after the user lifts their finger. Adding
the checkmark should be enough to show a cell's selection state. I would
only set the checkmark and leave `cell.selected` as is (I left it out in
the code above).
2. In `didSelectRow...`, toggle the selection state in your model data:
override func tableView(tableView: UITableView,
didSelectRowAtIndexPath indexPath: NSIndexPath) {
// Update model
let row = indexPath.row
locationList[row].selected = !locationList[row].selected
To update the UI, you now have two choices. Either ask the table view
for the cell at the index path and modify the cell directly:
// Either do this:
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
cell.accessoryType = locationList[row].selected ?
.Checkmark : .None
}
If you do that, I don't think you need to reload the cell explicitly.
Alternatively, tell the table view to reload the cell as you are doing
now. It will then call `tableView(_:cellForRowAtIndexPath:)` again,
which in turn will configure the cell with your model data:
// Or this:
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation:
.None)
Finally, fade out the cell selection:
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
3. If you are okay with keeping the cells deselected unless the user's
finger is onscreen, you don't need to implement `didDeselectRow...` at all.
(I typed this mostly without help from the compiler as I don't have a
Swift 2.x handy, so there may be some errors in the code above.)
Ole
More information about the swift-users
mailing list