Swift:点击一个单元格时更改所有 UITableViewCells 的文本颜色
Posted
技术标签:
【中文标题】Swift:点击一个单元格时更改所有 UITableViewCells 的文本颜色【英文标题】:Swift: Change text color of all UITableViewCells when one cell is tapped 【发布时间】:2015-06-30 01:20:13 【问题描述】:我在 Swift for ios 中有一个 UITableView,它应该一次只允许选择一个单元格。我进行了设置,以便点击在选中和未选中之间切换,长按将其设置为永久选中,这意味着它在视图加载时默认开始选中。当单元格超出滚动视图可见部分的边界然后重新进入时,我很难保持单元格标签的颜色,因此我使用我的数据模型来跟踪选择和永久选择的单元格。通过这样做,我绕过了 Apple 通过在界面生成器中选择“Single Selection”来制作 tableview 只允许单个单元格选择的方式。现在,我正在尝试构建自己的功能,以在点击另一个单元格时更改屏幕上可见的所有单元格的颜色。我目前正在尝试通过在点击每个单元格时循环遍历每个单元格并在该自定义单元格上调用将更改文本颜色的方法来做到这一点。问题是,它不起作用。如果我将单元格移出可见滚动区域然后再移入,单元格将正确着色,但如果我选择一个单元格,然后选择另一个单元格,则第一个单元格在可见时不会改变颜色。
这是我的代码。我已经删除了一些不相关的代码,所以如果您还有其他想看的内容,请告诉我。
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
如您所见,我目前正在从 didSelectRowAtIndexPath 方法内部调用 LocationTableViewController 的 colorAllCells 方法。 colorAllCells 方法循环遍历所有单元格并调用每个单元格的 setCellColor 方法,该方法将确定单元格颜色应该是什么并设置文本颜色。我已经验证了每个单元格的 setCellColor 方法都从循环中调用,并且它正确地确定了要设置的颜色。颜色只是不会改变。在遍历每个单元格并设置颜色后,我也尝试调用 self.tableView.reloadData(),但这也不起作用。
对于这个问题的任何帮助,我将不胜感激。如果您需要我澄清任何事情,请告诉我。谢谢!
【问题讨论】:
您是否尝试使用模型中每个单元格的设置来设置 cellForRow 中的单元格颜色?任何时候发生变化,你都可以在你的 tableview 上调用 reloadData,这些单元格就会更新。 我在 cellForRowAtIndexPath 方法中调用单元格的 setCellColor 方法。你指的是这个吗? @Jason247 你在很多层面上与框架作斗争,以至于我不知道从哪里开始——你让你的开发人员的生活变得更加艰难。请阅读此developer.apple.com/library/prerelease/ios/documentation/… @magma 恐怕这份文件并没有真正帮助我理解我的问题出在哪里。 【参考方案1】:我终于找到了解决办法。如果我在调用 tableView.cellForRowAtIndexPath 之前删除对 self 的引用,并将代码从 colorAllCells 方法移动到 didSelectRowAtIndexPath 方法中,那么它可以工作。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
if indexPath.row != 0
// Color all of the cells
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)
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? PlayerLocationCell
cell.setCellColor()
此解决方案有效。但是,当我将代码放在 didSelectRowAtIndexPath 方法中时,我不明白为什么它会起作用,但是如果我将该代码取出并将其放入自己的函数中然后调用该函数,它就不起作用。有谁知道这是为什么?
【讨论】:
当您滚动并且单元格被回收到不同的行/部分时会发生什么?他们得到正确的颜色吗?【参考方案2】:您需要一些方法来管理视图控制器中单元格选择的状态。我会用 Set 来做,像这样:
class LocationTableViewController: UITableViewController
var selectedIndexPaths = Set<NSIndexPath>()
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
self.selectedIndexPaths.insert( indexPath )
if let cell = tableView.cellForRowAtIndexPath( indexPath ) as? PlayerLocationCell
// Change color of the existing cell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
if let cell = tableView.dequeueReusableCellWithIdentifier( "addDataCell" )as? PlayerLocationCell
if self.selectedIndexPaths.contains( indexPath )
// Change color of the cell just dequeued/created
return cell
fatalError( "Could not dequeue cell of type 'PlayerLocationCell'" )
此外,您应该使用dequeueReusableCellWithIdentifier:
来重用表格视图单元格,而不是在您的tableView:cellForRowAtIndexPath
方法中创建新单元格。
【讨论】:
感谢 dequeueRe... 建议。我在另一张桌子上有这样的东西,但忘了在这张桌子上改变它。但是,关于您建议管理单元格选择的方法,我已经在我的数据模型中使用数组来执行此操作。 pokerLibrary.currentLog.locationList[i].selected = false。这工作正常,单元格不会因为某种原因而改变颜色,而不会将单元格移出视图然后再移回。 好的,我尝试将 dispatch_async(dispatch_get_main_queue()) 放在单元格的 setCellColor 方法内的代码周围,但没有奏效。 @Jason247 没有任何迹象表明您明确使用了除主线程之外的任何线程。 @magma 你是对的。我没有使用其他线程。不确定 Apple 的某些框架是否出于某种原因使用了其他线程。【参考方案3】:尝试在主线程上调用colorAllCells()
函数。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
if indexPath.row != 0
// Color all of the cells
dispatch_async(dispatch_get_main_queue(),
self.colorAllCells()
)
然而,这会阻止你的 UI。
【讨论】:
没有迹象表明他不是以上是关于Swift:点击一个单元格时更改所有 UITableViewCells 的文本颜色的主要内容,如果未能解决你的问题,请参考以下文章
点击 tableview 单元格时如何更改 UIImage 颜色?
点击/ reloadData不更改单元格时TableView单元格消失?