使用UITableView时如何保持对象的引用?

时间:2017-11-04 14:20:35

标签: swift uitableview

我面临的问题可能是对可重复使用细胞的概念缺乏了解。我要说,要创建30行,每行都有一个UISwitch。

当我切换其中一个开关时,它的行为会影响其他29个。重点是:据我所知,iOS并不会立即创建所有这些,而是​​等到当TableView向上和向下滚动时重用单元格。

如何保留这些重用对象的副本并告诉iOS为交换机设置正确的值?

我已经考虑将细胞附加到[UISwitch],但我无法将所有30个细胞放在那里,看看:

...

var switches = [UISwitch]()

...

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Field10Cell", for: indexPath) as! Field10TableViewCell

    ...

    //cell.value is a UISwitch
    if !switches.contains(cell.value) {
        switches.append(cell.value)
    }

    return cell
}

1 个答案:

答案 0 :(得分:5)

您可以创建一个存储已按下开关的单元格索引的集合。

var activeSwitches = Set<IndexPath>()

每当用户按下单元格上的开关时,您将其存储在以下集合中:

activeSwitches.insert(indexPath)

如果您需要检查交换机是否已激活,只需检查其容器单元的indexPath是否处于活动开关中,如下所示:

if activeSwitches.contains(indexPath) {
    // do something
}

为了知道用户何时按下特定开关,我建议使用以下内容:

  1. 在cellForRowAtIndexPath中将当前indexPath保存到Field10TableViewCell中。
  2. 在Field10TableViewCell上创建一个协议并添加一个委托。

    protocol Field10Delegate {
        func didChangeSwitch(value: Bool, indexPath: IndexPath)
    }
    
    class Field10TableViewCell {
        var delegate: Field10Delegate?
        var indexPath: IndexPath?
        @IBOutlet weak var fieldSwitch: UISwitch! // Can't use 'switch' as a variable name
    
        @IBAction func switchValueChanged(_ sender: UISwitch) {
            if let indexPath = indexPath {
                delegate?.didChangeSwitch(value: sender.isOn, indexPath: indexPath)
            }
        }
    
  3. 创建单元格时,将视图控制器设置为委托

    let cell = tableView.dequeueReusableCell(withIdentifier: "Field10Cell", for: indexPath) as! Field10TableViewCell
    cell.delegate = self
    cell.indexPath = indexPath
    
  4. 让您的视图控制器符合协议:

    extension ViewController: Field10Delegate {
        /* Whenever a switch is pressed on any cell, this delegate will
           be called. This is a good place also to trigger a update to
           your UI if it has to respond to switch changes.
         */
        func didChangeSwitch(value: Bool, indexPath: IndexPath) {
            if value {
                activeSwitches.insert(indexPath)
            } else {
                activeSwitches.remove(indexPath)
            }
            updateUI()
        }
    }
    
  5. 通过上述内容,您可以随时了解哪些开关处于活动状态,您可以使用此信息处理出列单元格。