Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/104.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何在单元格渲染后检查tableview上的复选标记图标(附件视图)?_Ios_Swift_Uitableview_Tableview_Accessorytype - Fatal编程技术网

Ios 如何在单元格渲染后检查tableview上的复选标记图标(附件视图)?

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

我有一个模型数据,它有一个布尔值,表示是否应该显示复选标记(accessoryType是.checkmark)

例如,我希望在开始时选中五行中的两行(根据我所说的模型)。。。问题是,我可以显示复选标记,但在我点击它们之后,切换无法正常工作:

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