【问题标题】:Reusable tableview cells affecting each other without interaction可重复使用的表格视图单元格相互影响而无需交互
【发布时间】:2017-02-22 14:57:36
【问题描述】:

我第一次尝试在 Swift 中完全以编程方式制作应用程序,但在使用 UITableViews 时遇到了问题。 我创建了一个自定义的可重用单元格,我称之为“exerciseCell”,其中有一个 UILabel、一个 UIImageview 和一个 UISwitch。

我的问题是,当我选择第 0 行上的开关时,它也会打开第 3 行和第 6 行上的开关。这对于每个单元格都是一样的,它们分别影响大约三个单元格。 此表格视图的目的是能够选择您想要的练习列表中的哪些练习,但每个练习都需要能够独立选择。

这是单元格的代码:

class exerciseCell: UITableViewCell {

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setupViews()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

var cellSelected:Bool = false

let excersiseLabel: UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.textColor = UIColor.red
    label.textAlignment = NSTextAlignment.center
    return label
}()
let excersiseImage: UIImageView = {
    let image = UIImageView()
    image.backgroundColor = UIColor.blue
    image.translatesAutoresizingMaskIntoConstraints = false
    return image
}()

let thisSwitch: UISwitch = {
    let thisSwitch = UISwitch()
    thisSwitch.isOn = false
    thisSwitch.translatesAutoresizingMaskIntoConstraints = false
    return thisSwitch

}()

func setupViews() {
    addSubview(excersiseLabel)
    addSubview(excersiseImage)
    addSubview(thisSwitch)
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["v0": excersiseLabel]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-101-[v0(100)]-101-|", options: .alignAllCenterX, metrics: nil, views: ["v0": excersiseImage]))
   addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-120-[v0(100)]-120-|", options: NSLayoutFormatOptions.alignAllCenterX, metrics: nil, views: ["v0": thisSwitch]))

    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-12-[v0(30)]-8-[v1(100)]-12-[v2(30)]-12-|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": excersiseLabel, "v1": excersiseImage, "v2": thisSwitch]))

}

}

还有cellForRow如下:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    var thisCell = UITableViewCell()

    if tableView == self.tableView {
        let aCell = tableView.dequeueReusableCell(withIdentifier: "thirdCellID", for: indexPath) as! exerciseCell
        aCell.excersiseLabel.text = "\(mobility[indexPath.row])"
        aCell.thisSwitch.tag = indexPath.row
        thisCell = aCell
    }
    return thisCell

}

如何让单元格独立响应用户?如果需要澄清,我可以提供更多代码。

【问题讨论】:

    标签: ios swift uitableview uiswitch


    【解决方案1】:

    由于单元格被表格视图重用,它们不会保留其开关设置。您将需要一个外部构造来跟踪选择了哪些单元格。

    该单元需要让您的控制器知道其开关何时被切换(可能通过委托),此时您将更新您的(例如)BOOL 数组。

    然后,在 cellForRowAtIndexPath 中,您需要一些代码来将正确的值应用于单元格。比如:

    cell.switch.isOn = cellSwitchStates[indexPath.row]
    

    【讨论】:

      【解决方案2】:

      这是 uitableviewcell 中显示的常见问题。解决这个问题的最好方法是使用 Objects 配置单元格。

      例如,在您的情况下,您需要在 Tableview 中显示锻炼列表。 因此,使用布尔变量(例如var switchState: Bool)为练习创建一个模态类。

      class Exercise: NSObject {
      
          var exerciseName : String?
          var switchState : Bool = false
      
          init (exerciseName : String?,switchState : Bool) {
              super.init()
              self.exerciseName = exerciseName
              self.switchState = switchState
          } 
      }
      

      然后使用默认的 switchState 值填充一组练习对象(例如 var exercises : [Exercise])。

      然后TableView numberofrows count取自exists数组...返回exists.count,

      cellForRowAt indexPath 从练习数组中获取正确的练习对象,例如:var exercise = exercises[indexpath.row],现在我们有正确的对象了吗?所以在您的自定义单元格中创建一种方法fun configureCellWith(exercise:Exercise)(在您的情况下单元格将是aCell) 所以从 cellForRowAt indexPath 调用这个单元格方法,并将我们的练习对象作为参数传递

      例如: aCell.configureCellWith(exercise) 而你在 exerciseCell 中的 configureCellWith() 方法应该是这样的

      // Write this method within exerciseCell
      func configureCellWith(exercise:Exercise) {
      
      privateExercise = exercise // privateExercise is a private Variable for exerciseCell so please create private var privateExercise : Exercise in exerciseCell
      
      thisSwitch.isOn = exercise.switchState 
      
      }
      

      然后在练习单元中为您的开关创建一个操作方法

      thisSwitch.addTarget(self, action: Selector("switchTriggered:"), forControlEvents: .ValueChanged );
      
      
      func switchTriggered(sender: AnyObject) {
      
          let switch = sender as! UISwitch
          privateExercise.switchState = switch.isOn
      
      }
      

      现在一切看起来都很好..请打开/关闭第 0 行并检查它是否影响其他行。谢谢。

      【讨论】:

      • 非常感谢@Aby,这阻止了它们相互影响,但是如果我在表格视图中向下滚动然后向上滚动,开关将返回到关闭位置。我可能没有正确完成私有变量,它一直给我关于未分配练习名称的错误,所以我只是将名称初始化为“”。
      • 我认为这是因为 switchTriggered 方法没有被识别。我在函数中放了一个 print("Switch Triggered") 但它从未显示。选择器样式是否正确?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 2022-10-13
      • 2017-01-02
      • 1970-01-01
      相关资源
      最近更新 更多