如何将原型单元中的UISwitch状态传递回UITableView

时间:2019-04-23 09:44:38

标签: ios swift uiswitch

我在原型单元中有一个UISwitch,我不知道如何将状态传递回我的UITableView。我需要传递回开关的状态来更新对象以反映新状态。

我已经尝试过以下问题,但是它们都在Objective C中(我几乎不能写Swift,所以我在努力寻找如何适应它们的方法) Access UISwitch in Prototype CellHow to retrieve UISwitch state in each of my UITableView cells?

我目前正在尝试使this解决方案正常工作。

以下是在UITabelView中构建单元的性能指标:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProgrammeToggleTableViewCell", for: indexPath) as? ProgrammeToogleTableViewCell else { return UITableViewCell() }

        cell.setTitle(text: programmes[indexPath.row].name)

        cell.programmeToggle.tag = indexPath.row
        print(cell.programmeToggle.tag)
        cell.programmeToggle.isOn = programmes[indexPath.row].active
        cell.programmeToggle.addTarget(self, action: #selector(ProgrammeTableViewController.switchAtValueChanged(programmeToggle: UISwitch, indexPath: IndexPath)), for: UIControl.Event.valueChanged)

        return cell
    }

我稍后尝试使用以下命令访问交换机:

    @objc func switchAtValueChanged(programmeToggle: UISwitch, indexPath: IndexPath) {

        if programmeToggle.tag == 1 {
            var programmes[indexPath.row].active = UISwitch.isOn
            print(programmes[1].active)
        }
    }

programmes是一个对象数组。

var programmes[indexPath.row].active = UISwitch.isOn行当前给我以下错误: Consecutive statements on a line must be separated by ';' Type annotation missing in pattern Value of type '[Int]' has no member 'active'

我想使用开关的状态来编辑programmes数组中对象之一的值。由于我对Swift缺乏经验,所以我不知道我是在树错树皮还是在工作时这是可行的解决方案。

感谢您的帮助,很高兴在需要时提供任何进一步的信息。

3 个答案:

答案 0 :(得分:1)

它不像您尝试的那么琐碎。当您使表格视图单元出队时,这意味着它将创建一个新单元或重用一个旧单元。例如,您有100个单元格,但一次只能看到10个单元格。当用户向下滚动时,第一个单元格消失,然后重新用作第11个单元格。因此,这在物理上是同一单元格。并在其开关上调用add target-selector意味着您现在在该开关上有2个动作。但是您可能发现这种情况下仍然存在其他问题(例如无法将索引路径注入方法)。

您只需要使用表来表示数据。因此,您必须在其他地方修改数据。

您遇到的最简单的解决方案是将类添加到单元格本身中。只需在单元格中为行方法分配它即可:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProgrammeToggleTableViewCell", for: indexPath) as? ProgrammeToogleTableViewCell else { return UITableViewCell() }
    cell.programme = programmes[indexPath.row]
    return cell
}

现在将所有逻辑放入单元格中,例如:

var programme: Programme? {
    didSet {
        refresh()
    }
}
func refresh() {
    guard let programme = programme else { return }
    programmeToggle.isOn = programme.active
}

@IBAction private func switchToggled() {
    self.programme?.active = programmeToggle.isOn
}

现在,开关的动作会影响分配的程序。您的情况就足够了。

作为替代方案,在许多情况下,您需要使用委托。您的视图控制器将定义一个已切换开关的协议,并将其分配给您的单元格:

cell.progremmeID = progremme.id
cell.delegate = self
return cell

然后是协议:

func programmeCell(_ sender: ProgrammeToogleTableViewCell, didToggleProgremme programmeID: String, toActive flag: Bool) {
    programmes.first(where: { $0.id == programmeID })?.active = flag
}

答案 1 :(得分:1)

首先,您需要在表格视图单元格中创建回调。

 class ProgrammeToogleTableViewCell: UITableViewCell {

   @IBOutlet weak var switchUI: UISwitch!

   // callback to get action of switch status
   var callBackSwitchState:((Bool) -> (Void))?

  // Create action for value change event on switch
   @IBAction func switchAtValueChanged(programmeToggle: UISwitch) {
     callBackSwitchState?(programmeToggle.isOn)
   }
}

现在在cellForRowAt数据源方法中,您需要为刚刚创建的此回调设置值,以获取开关的状态:

在表格视图类中:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> 
  UITableViewCell {
   guard let cell = tableView.dequeueReusableCell(withIdentifier: 
     "ProgrammeToggleTableViewCell", for: indexPath) as? ProgrammeToogleTableViewCell 
     else { return UITableViewCell() }
    cell.tag = indexPath.row

    // Implement the callback to get the status of switch:
    cell.callBackSwitchState = { isOn in
    print("Your Switch status = \(isOn)")

    // isOn is your switch status. You can update your object here.
   }

 // Your other code here ....
 return cell
}

答案 2 :(得分:0)

只需删除以下行中的var-

var programs [indexPath.row] .active = UISwitch.isOn