I have a UITableView in Swift for iOS that is supposed to allow only one cell to be selected at a time. I have it set up so that taps toggle between selected and not selected, and a long press sets it to permanently selected, which means it starts out selected by default when the view loads. I was having difficulty with keeping the cells' label colored when the cell went outside the bounds of the visible part of the scrollview and then reentered it, so I used my data model to keep track of what cells were selected and permanently selected. By doing so, I have bypassed Apple's way of making a tableview allow only single cell selection by selecting "Single Selection" in interface builder. Now I am trying to build out my own functionality to change the color of all cells visible on the screen when another cell is tapped. I am currently attempting to do this by looping through each cell when it is tapped and calling a method on that custom cell that will change the text color. The problem is, it isn't working. If I move the cells out of the visible scrolling area and then back in, the cells will be colored properly, but if I select one cell, and then another, the first cell won't change color while it is visible.
Here is my code. I have removed some code that was irrelevant, so if there is something else you would like to see, let me know.
import Foundation
import UIKit
class AddDataViewController : UIViewController {
@IBOutlet weak var locationTableView: UITableView!
let locationTableViewController = LocationTableViewController()
override func viewWillAppear(animated: Bool) {
// Set the data source and delgate for the tables
self.locationTableView.delegate = self.locationTableViewController
self.locationTableView.dataSource = self.locationTableViewController
// Refresh the tables
self.locationTableView.reloadData()
// Add the table view controllers to this view
self.addChildViewController(locationTableViewController)
}
override func viewDidLoad(){
super.viewDidLoad()
// Create a tap gesture recognizer for dismissing the keyboard
let tapRecognizer = UITapGestureRecognizer()
// Set the action of the tap gesture recognizer
tapRecognizer.addTarget(self, action: "dismissKeyboard")
// Update cancels touches in view to allow touches in tableview to be detected
tapRecognizer.cancelsTouchesInView = false
// Add the tap gesture recognizer to the view
self.view.addGestureRecognizer(tapRecognizer)
}
}
class LocationTableViewController : UITableViewController, UITableViewDelegate, UITableViewDataSource {
var locationSelected : String = ""
func colorAllCells() {
for section in 0 ... self.tableView.numberOfSections() - 1 {
for row in 0 ... self.tableView.numberOfRowsInSection(section) - 1 {
if row != 0 {
let indexPath = NSIndexPath(forRow: row, inSection: section)
let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! PlayerLocationCell
cell.indexPath = indexPath.row - 1
cell.setCellColor()
}
}
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row != 0 {
// Color all of the cells
self.colorAllCells()
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = PlayerLocationCell(style: UITableViewCellStyle.Value2, reuseIdentifier: "addDataCell")
cell.selectionStyle = UITableViewCellSelectionStyle.None
if indexPath.row != 0 {
cell.textLabel!.text = pokerLibrary.currentLog.locationList[indexPath.row - 1].name
cell.indexPath = indexPath.row - 1
cell.setCellColor()
}
return cell
}
}
class PlayerLocationCell : UITableViewCell {
let selectedColor = UIColor.greenColor()
let deselectedColor = UIColor.grayColor()
let permanentlySelectedColor = UIColor.blueColor()
var shouldHighlightText : Bool = true
var indexPath : Int = 0
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "cellPressed")
longPressRecognizer.minimumPressDuration = 1.0
longPressRecognizer.cancelsTouchesInView = false
self.addGestureRecognizer(longPressRecognizer)
let tapRecognizer = UITapGestureRecognizer(target: self, action: "cellTapped")
tapRecognizer.cancelsTouchesInView = false
self.addGestureRecognizer(tapRecognizer)
}
func setCellColor() {
if shouldHighlightText {
if self.isPermanentlySelected() {
self.textLabel!.textColor = self.permanentlySelectedColor
}
else if self.isCurrentlySelected() {
self.textLabel!.textColor = self.selectedColor
}
else {
self.textLabel!.textColor = self.deselectedColor
}
}
}
func cellTapped() {
if shouldHighlightText {
self.setPermanentlySelected(false)
if self.isCurrentlySelected() {
self.setSelectedProperty(false)
self.setCellColor()
}
else {
self.setSelectedProperty(true)
self.setCellColor()
}
}
}
func cellPressed() {
if self.shouldHighlightText {
if !self.isPermanentlySelected() {
self.setPermanentlySelected(true)
self.setCellColor()
}
}
}
func setPermanentlySelected(b : Bool) {
if b {
// Set all other locations to false
for i in 0 ... pokerLibrary.currentLog.locationList.count - 1 {
pokerLibrary.currentLog.locationList[i].selected = false
pokerLibrary.currentLog.locationList[i].permanentlySelected = false
}
}
pokerLibrary.currentLog.locationList[self.indexPath].permanentlySelected = b
}
func isPermanentlySelected() -> Bool {
return pokerLibrary.currentLog.locationList[self.indexPath].permanentlySelected
}
func setSelectedProperty(b : Bool) {
if b {
// Set all other locations to false
for i in 0 ... pokerLibrary.currentLog.locationList.count - 1 {
pokerLibrary.currentLog.locationList[i].selected = false
pokerLibrary.currentLog.locationList[i].permanentlySelected = false
}
}
pokerLibrary.currentLog.locationList[self.indexPath].selected = b
}
func isCurrentlySelected() -> Bool {
return pokerLibrary.currentLog.locationList[self.indexPath].selected
}
}
As you can see, I am currently calling the LocationTableViewController's colorAllCells method from inside the didSelectRowAtIndexPath method. The colorAllCells method loops through all cells and calls each cell's setCellColor method, which will determine what the cell color should be and set the text color. I have verified each of the cell's is having its setCellColor method called from the loop, and it is correctly determining which color to set. The color just won't change. I have also tried calling self.tableView.reloadData() after I have looped through each cell and set the color, but that didn't work either.
I would appreciate any help with this issue. If you need me to clarify anything, let me know. Thanks!