UITableViewCell选择挑战

时间:2015-12-11 08:28:04

标签: ios swift uitableview

我为这个问题创建了一个简单的演示应用程序,这并不重要,但我正在寻找一个优雅的解决方案。我有一个包含多个部分的分组tableview,每个部分允许选择一个项目。这是代码:

class TableViewController: UITableViewController {

    let sections = ["A", "B", "C", "D", "E", "F"]
    let items = [
                 ["one", "two", "three", "four"],
                 ["one", "two", "three", "four"],
                 ["one", "two", "three", "four"],
                 ["one", "two", "three", "four"],
                 ["one", "two", "three", "four"],
                 ["one", "two", "three", "four"]
                 ]

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return sections.count
    }

    override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section]
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items[section].count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)     // option 1
        // let cell = UITableViewCell(style: .Default, reuseIdentifier: "Cell")     // option 2
        cell.textLabel?.text = items[indexPath.section][indexPath.row]
        return cell
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
        let cell = tableView.cellForRowAtIndexPath(indexPath)
        let section = indexPath.section

        for rowNumber in 0..<tableView.numberOfRowsInSection(section) {
            let tempPath = NSIndexPath(forRow: rowNumber, inSection: section)
            let tempCell = tableView.cellForRowAtIndexPath(tempPath)
            tempCell?.accessoryType = .None
        }

        cell?.accessoryType = .Checkmark
    }
}

表格很长,表示滚动查看所有项目。现在,如果我选择选项1(dequeueReusableCellWithIdentifier)并在第1部分中选择一行,则自动在第5部分被选中(可以通过滚动看到)。显然这不是故意的。如果我选择选项2,那么这不会发生,但是一旦滚动后它从视图中消失,该行就会被取消选择。也不是故意的。

到目前为止,我的解决方案是添加一个变量selectedCellIndices,这是一个包含每个部分所选indexPath.row的数组。这有效,但相当丑陋。

有关整洁解决方案的任何建议吗?

3 个答案:

答案 0 :(得分:2)

问题:

当一行滚动屏幕并且新行变得明显可见时,滚动离开屏幕的行的单元格将重新用于刚刚可见的行。目前,您只在单元格上设置复选标记。需要记住的一点是, ROW是数据 CELL是该数据的视图

如果您更新单元格上的checkMark,那么只更新视图。当行滚动屏幕时,该单元被回收或重复使用。

解决方案:

应用 MVC 技术。当您通过放置或删除复选标记来更新单元格时,您只需更新视图。接下来,您还需要更新模型。按模型我的意思是数据模型。

尝试创建数据类或数据模型:

import Foundation

class ChecklistItem {
    var text = ""
    var checked = false

    func toggleChecked() {
    checked = !checked
     }
   }

在你的控制器中创建一个数组,它将保存上述声明的类模型数据类型的数据,如下所示:

var items: [ChecklistItem]

didSelectRowAtIndex 功能中,您可以执行以下操作:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

if let cell = tableView.cellForRowAtIndexPath(indexPath) {

  // get the object from the array that was tapped by using the index path of the row
  let item = items[indexPath.row]

  // Toggle the checkMark, this method was declared within the data model as it was responsible for manipulating or updating the data. 
  item.toggleChecked()

  if item.checked {
  cell.accessoryType = .Checkmark
} else {
  cell.accessoryType = .None
}

}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

以上是您的数据模型。现在,当您更新单元格时,还要通过声明该对象的checked变量true或false来更新数据模型。 True表示该行/单元格的复选标记,false表示没有复选标记。这样你就可以坚持你的复选标记。您还需要将这些对象保存到上面声明的items数组中。

如果您需要更多信息,请与我们联系。或者如果有些事情令人困惑。我希望这会有所帮助。

答案 1 :(得分:1)

选项1:

  • allowsMultipleSelection上启用tableView
  • tableView:didSelectRowAtIndexPath:中,检查您是否已在该部分中选择了一个单元格(tableView.indexPathsForSelectedRows上的一些过滤)。如果是这种情况,请取消选择。

这将使用标准iOS选择样式(彩色背景),但您可以在自定义表格单元格setSelected:中更改它(添加/删除附件),并配置表格单元格& #39; s selectionStyleNone。请记住在setSelected中调用super,您仍需要设置内部selected标记。

选项2:执行您的建议,将选择保留在单独的数组中,使用它在表格视图单元格出列时配置附件。

答案 2 :(得分:0)

显然,您应该将cell.accessoryType = .None添加到cellForRowAtIndexPath,因为可以重复使用单元格,而不会更改其最后的外观。