Ios 如何在单元格渲染后检查tableview上的复选标记图标(附件视图)?
我有一个模型数据,它有一个布尔值,表示是否应该显示复选标记(accessoryType是.checkmark) 例如,我希望在开始时选中五行中的两行(根据我所说的模型)。。。问题是,我可以显示复选标记,但在我点击它们之后,切换无法正常工作:Ios 如何在单元格渲染后检查tableview上的复选标记图标(附件视图)?,ios,swift,uitableview,tableview,accessorytype,Ios,Swift,Uitableview,Tableview,Accessorytype,我有一个模型数据,它有一个布尔值,表示是否应该显示复选标记(accessoryType是.checkmark) 例如,我希望在开始时选中五行中的两行(根据我所说的模型)。。。问题是,我可以显示复选标记,但在我点击它们之后,切换无法正常工作: func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if let cell = tableView.cellForRow(at: index
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
model[indexPath.row].isCellSelected = true
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
model[indexPath.row].isCellSelected = false
}
}
And here is a cellForRowAt:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = data.subtitle != nil ? kSubtitleID : kNormalID
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
return cell
}
我可以这样显示复选标记:
cell.accessoryType = data.isCellSelected ? .checkmark : .none
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
let isCellSelected = !(model[indexPath.row].isCellSelected)
model[indexPath.row].isCellSelected = isCellSelected
tableView.reloadRows(at: [indexPath], with: .none)
}
}
但当我点击它时,它会导致它被选中(allowsMultipleSelection设置为true),它不会被切换,而是第一次保持不变
这是我使用的模型。其实很简单:
struct CellModel{
var title:String?
var subtitle:String?
var isCellSelected:Bool = false
}
您应该仅在
tableView:didSelectRowAt:
中执行切换,然后重新加载必要的单元格。您应该省略tableView:did取消选择rowat:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
// Toggle the value - true becomes false, false becomes true
model[indexPath.row].isCellSelected = !model[indexPath.row].isCellSelected
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .none)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = data.subtitle != nil ? kSubtitleID : kNormalID
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
// Set the checkmark or none depending on your model value
cell.inputAccessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
编辑:
仅用于单选+取消选择所选项目的功能:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Loop through all model items
for (index, item) in model.enumerated() {
if (index == indexPath.row) {
// Toggle tapped item
item.isCellSelected = !item.isCellSelected
} else {
// Deselect all other items
item.isCellSelected = false
}
}
tableView.reloadData();
}
您应该仅在
tableView:didSelectRowAt:
中执行切换,然后重新加载必要的单元格。您应该省略tableView:did取消选择rowat:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
// Toggle the value - true becomes false, false becomes true
model[indexPath.row].isCellSelected = !model[indexPath.row].isCellSelected
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .none)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = data.subtitle != nil ? kSubtitleID : kNormalID
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
// Set the checkmark or none depending on your model value
cell.inputAccessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
编辑:
仅用于单选+取消选择所选项目的功能:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Loop through all model items
for (index, item) in model.enumerated() {
if (index == indexPath.row) {
// Toggle tapped item
item.isCellSelected = !item.isCellSelected
} else {
// Deselect all other items
item.isCellSelected = false
}
}
tableView.reloadData();
}
在拥有保存布尔值的模型之前,不必使用“选择”和“取消选择” 在tableview中选择方法
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if model[index.row].isCellSelected == true {
model[indexpath.row].isCellSelected = false
}
else {
model[indexpath.row].isCellSelected = true
}
tableview.reloadData
}
并在单元格中进行行检查
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if model[index.row].isCellSelected{
cell.accessoryType = .checkmark
}
else {
cell.accessoryType = .none
}
}
在拥有保存布尔值的模型之前,不必使用“选择”和“取消选择” 在tableview中选择方法
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if model[index.row].isCellSelected == true {
model[indexpath.row].isCellSelected = false
}
else {
model[indexpath.row].isCellSelected = true
}
tableview.reloadData
}
并在单元格中进行行检查
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if model[index.row].isCellSelected{
cell.accessoryType = .checkmark
}
else {
cell.accessoryType = .none
}
}
我所做的一切工作是:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let data = model[indexPath.row]
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
model[indexPath.row].isCellSelected = true
self.selectedData?(model.filter{$0.isCellSelected})
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let data = model[indexPath.row]
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
model[indexPath.row].isCellSelected = false
self.selectedData?(model.filter{$0.isCellSelected})
}
}
及
但我必须首先设置实际选择的单元格:
func setSelectedCells(){
let selectedIndexes = self.model.enumerated().compactMap { (index, element) -> IndexPath? in
if element.isCellSelected{
return IndexPath(row: index, section: 0)
}
return nil
}
selectedIndexes.forEach{
selectRow(at: $0, animated: false, scrollPosition: .none)
}
}
然后在ViewDidDisplay中调用它,因为我必须确保表已经绘制了它的内容(因为如果我们尝试一些还不存在的东西(单元格),这将失败)。这不是最好的方法,但它解决了带有初始状态的单个和多个选择的问题
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let data = model[indexPath.row]
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
model[indexPath.row].isCellSelected = true
self.selectedData?(model.filter{$0.isCellSelected})
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let data = model[indexPath.row]
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
model[indexPath.row].isCellSelected = false
self.selectedData?(model.filter{$0.isCellSelected})
}
}
及
但我必须首先设置实际选择的单元格:
func setSelectedCells(){
let selectedIndexes = self.model.enumerated().compactMap { (index, element) -> IndexPath? in
if element.isCellSelected{
return IndexPath(row: index, section: 0)
}
return nil
}
selectedIndexes.forEach{
selectRow(at: $0, animated: false, scrollPosition: .none)
}
}
然后在ViewDidDisplay中调用它,因为我必须确保表已经绘制了它的内容(因为如果我们尝试一些还不存在的东西(单元格),这将失败)。这不是最好的方法,但它解决了带有初始状态的单个和多个选择的问题,然后,
cellForRowAt
方法变得非常简单:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = data.subtitle != nil ? kSubtitleID : kNormalID
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
let isCellSelected = !(model[indexPath.row].isCellSelected)
cell.accessoryType = isCellSelected ? .checkmark : .none
model[indexPath.row].isCellSelected = isCellSelected
}
}
然后,didSelectRowAt
方法变得非常简单:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = data.subtitle != nil ? kSubtitleID : kNormalID
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
let isCellSelected = !(model[indexPath.row].isCellSelected)
cell.accessoryType = isCellSelected ? .checkmark : .none
model[indexPath.row].isCellSelected = isCellSelected
}
}
注意,我们必须切换标志,并根据新值更新单元格和模型
更好的是,您可以将.association type更新行替换为:
tableView.reloadRows(at: [indexPath], with: .none)
因此,该方法如下所示:
cell.accessoryType = data.isCellSelected ? .checkmark : .none
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
let isCellSelected = !(model[indexPath.row].isCellSelected)
model[indexPath.row].isCellSelected = isCellSelected
tableView.reloadRows(at: [indexPath], with: .none)
}
}
请注意,我们更新了模型
,然后重新加载将导致调用cellForRowAt
的单元格,并且该方法会根据模型考虑正确的配置
更一般地说,我建议使用一些StateController
对象来保持每个单元格/行的状态,并负责切换
不久前,我写了一整篇文章,这篇文章正是您需要做的,并展示了许多最佳实践:
然后,cellForRowAt
方法变得非常简单:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = data.subtitle != nil ? kSubtitleID : kNormalID
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
let isCellSelected = !(model[indexPath.row].isCellSelected)
cell.accessoryType = isCellSelected ? .checkmark : .none
model[indexPath.row].isCellSelected = isCellSelected
}
}
然后,didSelectRowAt
方法变得非常简单:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = data.subtitle != nil ? kSubtitleID : kNormalID
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
let isCellSelected = !(model[indexPath.row].isCellSelected)
cell.accessoryType = isCellSelected ? .checkmark : .none
model[indexPath.row].isCellSelected = isCellSelected
}
}
注意,我们必须切换标志,并根据新值更新单元格和模型
更好的是,您可以将.association type更新行替换为:
tableView.reloadRows(at: [indexPath], with: .none)
因此,该方法如下所示:
cell.accessoryType = data.isCellSelected ? .checkmark : .none
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let cell = tableView.cellForRow(at: indexPath) {
let isCellSelected = !(model[indexPath.row].isCellSelected)
model[indexPath.row].isCellSelected = isCellSelected
tableView.reloadRows(at: [indexPath], with: .none)
}
}
请注意,我们更新了模型
,然后重新加载将导致调用cellForRowAt
的单元格,并且该方法会根据模型考虑正确的配置
更一般地说,我建议使用一些StateController
对象来保持每个单元格/行的状态,并负责切换
不久前,我写了一整篇文章,这篇文章正是您需要做的,并展示了许多最佳实践:
@Whirlwind,您好,如果您只需要在表视图中显示所选内容,这并不复杂,在您的模型更新后,我将提供我的ans
这可以通过仅在didSelectRowAt
中维护isCellSelected
属性来实现。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
model[indexPath.row].isCellSelected = model[indexPath.row].isCellSelected ? false : true
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = "kNormalID"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
这里是cellForRowAt
您也可以在这里更改更多行。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
model[indexPath.row].isCellSelected = model[indexPath.row].isCellSelected ? false : true
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = "kNormalID"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
希望我向你表达了我最好的。如果我遗漏了什么,请告诉我。@Whirlwind,您好,如果您只需要在表视图中显示选择,这并不复杂,在您的模型更新后,我将在这里提供我的ans
这可以通过仅在didSelectRowAt
中维护isCellSelected
属性来实现。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
model[indexPath.row].isCellSelected = model[indexPath.row].isCellSelected ? false : true
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = "kNormalID"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
这里是cellForRowAt
您也可以在这里更改更多行。
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
model[indexPath.row].isCellSelected = model[indexPath.row].isCellSelected ? false : true
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = model[indexPath.row]
let identifier = "kNormalID"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath)
cell.textLabel?.text = data.title
cell.detailTextLabel?.text = data.subtitle
cell.accessoryType = data.isCellSelected ? .checkmark : .none
return cell
}
希望我向你表达了我最好的。如果我遗漏了什么,请告诉我。为什么不试试下面的内容呢
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
model[indexPath.row].isCellSelected = false
tableView.reloadRows(at: [indexPath], with: <UITableViewRowAnimation>)
}
}
func tableView(tableView:UITableView,在indexPath:indexPath中取消行){
如果let cell=tableView.cellForRow(at:indexPath){
cell.accessoryType=.none
模型[indexath.row].isCellSelected=false
tableView.reloadRows(位于:[indexath],带:)
}
}
为什么不试试下面的内容呢
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .none
model[indexPath.row].isCellSelected = false
tableView.reloadRows(at: [indexPath], with: <UITableViewRowAnimation>)
}
}
func tableView(tableView:UITableView,在indexPath:indexPath中取消行){
如果let cell=tableView.cellForRow(at:indexPath){
cell.accessoryType=.none
模型[indexath.row].isCellSelected=false
tableView.reloadRows(位于:[indexath],带:)
}
}
嘿,成功了,谢谢!我记得我以前有一次对这种方法有过问题,但我不能确定它是否是相同的情况(可能不是),但我还是跳过了,哈。没问题。确保您的tableView:cellForRowAt:
m