Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.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
Swift 如何保持对象';使用UITableView时的引用?_Swift_Uitableview - Fatal编程技术网

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

Swift 如何保持对象';使用UITableView时的引用?,swift,uitableview,Swift,Uitableview,我面临的问题可能是对可重用单元的概念缺乏理解。我有30行要创建,每个行都有一个UISwitch 当我切换其中一个开关时,它的行为会影响其他开关。要点是:据我所知,iOS并不是一次创建所有单元格,而是在上下滚动TableView时等待重用单元格 我如何保存这些重用对象的副本,并告诉iOS为交换机设置正确的值 我曾考虑将这些单元格附加到[UISwitch]上,但我无法将所有30个单元格都放在那里,看: ... var switches = [UISwitch]() ... override f

我面临的问题可能是对可重用单元的概念缺乏理解。我有30行要创建,每个行都有一个UISwitch


当我切换其中一个开关时,它的行为会影响其他开关。要点是:据我所知,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
}

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

var activeSwitches = Set<IndexPath>()
如果需要检查开关是否已激活,只需检查其容器单元格的indexPath是否位于活动开关中,如下所示:

if activeSwitches.contains(indexPath) {
    // do something
}
为了了解用户何时按下特定开关,我建议使用以下选项:

  • 在cellForRowAtIndexPath中,将当前indexPath保存到Field10TableViewCell中
  • 在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)
            }
        }
    
  • 创建单元时,将视图控制器设置为委托

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

    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()
        }
    }
    

  • 通过以上操作,您随时都可以知道哪些开关处于活动状态,并且可以使用此信息处理已退出队列的单元格。

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

    var activeSwitches = Set<IndexPath>()
    
    如果需要检查开关是否已激活,只需检查其容器单元格的indexPath是否位于活动开关中,如下所示:

    if activeSwitches.contains(indexPath) {
        // do something
    }
    
    为了了解用户何时按下特定开关,我建议使用以下选项:

  • 在cellForRowAtIndexPath中,将当前indexPath保存到Field10TableViewCell中
  • 在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)
            }
        }
    
  • 创建单元时,将视图控制器设置为委托

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

    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()
        }
    }
    


  • 通过以上内容,您随时都可以知道哪些开关处于活动状态,并且您可以使用此信息处理排队的单元格。

    “当我切换其中一个开关时,其行为应该会影响其他29个开关。”您可以进一步解释一下吗?假设我切换了开关一。在“onvaluechanged”上,我想禁用所有其他29个开关,但我不能,因为我还没有它们的实例(我猜),您的想法是错误的。如果在切换一个开关时所有开关都应该具有相同的状态,则声明一个布尔属性以保持当前状态和一个
    iAction
    。将单元格中的按钮连接到操作。如果开关更改了值,请更新boolean属性,重新加载表视图并相应地在cellForRow中设置开关的状态。@vadian我应该在哪里声明该变量?在单元格或tableview类中?在控制器中。“当我切换其中一个开关时,它的行为应该会影响其他29个开关。”请您对此进行详细解释。假设我切换开关一。在“onvaluechanged”上,我想禁用所有其他29个开关,但我不能,因为我还没有它们的实例(我猜),您的想法是错误的。如果在切换一个开关时所有开关都应该具有相同的状态,则声明一个布尔属性以保持当前状态和一个
    iAction
    。将单元格中的按钮连接到操作。如果开关更改了值,请更新boolean属性,重新加载表视图并相应地在cellForRow中设置开关的状态。@vadian我应该在哪里声明该变量?在单元格中或在控制器的tableview类中。
    ==true
    是冗余的<代码>如果值{而且顺便说一句,无需为交换机添加IBOutlet。只需使用sender即可。UISwitch没有value属性。您应该使用它的isOn属性。
    sender.isOn
    谢谢您的更正@LeoDabus!我是按内存编码的,容易出错:-/@FelipeFerri通常不需要。但这不会有什么坏处:)通常您是t强烈建议不要保留索引路径数组/集合。例如,当您通过拖放实现行重新排序时,索引路径可以在不调用
    cellForRow
    的情况下更改。
    ==true
    是多余的。
    如果值{
    而且顺便说一句,无需为交换机添加IBOutlet。只需使用sender即可。UISwitch没有value属性。您应该使用它的isOn属性。
    sender.isOn
    谢谢您的更正@LeoDabus!我是按内存编码的,容易出错:-/@FelipeFerri通常不需要。但这不会有什么坏处:)通常您是强烈建议不要保留索引路径数组/集合。例如,当您通过拖放实现行重新排序时,索引路径可以在不调用
    cellForRow
    的情况下更改。