Ios 可重用的tableview单元相互影响,无需交互

Ios 可重用的tableview单元相互影响,无需交互,ios,swift,uitableview,uiswitch,Ios,Swift,Uitableview,Uiswitch,我第一次尝试在Swift中完全以编程方式制作应用程序,但在使用UITableView时遇到了问题。 我创建了一个自定义的可重用单元,称为exerciseCell,其中有一个UILabel、一个UIImageview和一个UISwitch 我的问题是,当我选择第0行上的开关时,它也在打开第3行和第6行上的开关。这对每个细胞都是一样的,每个细胞影响大约三个细胞。 此tableview的目的是能够选择需要练习列表的练习,但每个练习都需要能够独立选择 以下是单元格的代码: class exerciseC

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

我的问题是,当我选择第0行上的开关时,它也在打开第3行和第6行上的开关。这对每个细胞都是一样的,每个细胞影响大约三个细胞。 此tableview的目的是能够选择需要练习列表的练习,但每个练习都需要能够独立选择

以下是单元格的代码:

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

}

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

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

单元格需要让您的控制器知道其开关何时被切换(可能是通过委托),此时您需要更新布尔的实例数组

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

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

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

单元格需要让您的控制器知道其开关何时被切换(可能是通过委托),此时您需要更新布尔的实例数组

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

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

这是uitableviewcell中显示的常见问题。解决此问题的最佳方法是使用对象配置单元

例如,在本例中,您需要在Tableview中显示练习列表。 因此,创建一个模态类,用于使用布尔变量进行练习,例如var switchState:Bool

然后使用默认的switchState值false填充练习对象数组,例如var exercises:[Exercise]

然后从练习数组中获取TableView numberofrows计数。。。返回练习。计数

在cellForRowAt indexPath中 从练习数组中获取正确的练习对象,例如:var exercise=exercises[indexath.row],现在我们有了正确的对象,对吗?因此,创建一个方法fun ConfigureCellWithExecute:在您的自定义单元格内进行练习,在您的案例中,单元格将是aCell 因此,从cellForRowAt indexPath调用此cell方法,并将我们的练习对象作为参数传递

e、 g.:aCell.configureCellWithexercise 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 

}
然后在exerciseCell中为开关创建一个动作方法

thisSwitch.addTarget(self, action: Selector("switchTriggered:"), forControlEvents: .ValueChanged );


func switchTriggered(sender: AnyObject) {

    let switch = sender as! UISwitch
    privateExercise.switchState = switch.isOn

}

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

这是uitableviewcell中显示的常见问题。解决此问题的最佳方法是使用对象配置单元

例如,在本例中,您需要在Tableview中显示练习列表。 因此,创建一个模态类,用于使用布尔变量进行练习,例如var switchState:Bool

然后使用默认的switchState值false填充练习对象数组,例如var exercises:[Exercise]

然后从练习数组中获取TableView numberofrows计数。。。返回练习。计数

在cellForRowAt indexPath中 从练习数组中获取正确的练习对象,例如:var exercise=exercises[indexath.row],现在我们有了正确的对象,对吗?因此,创建一个方法fun ConfigureCellWithExecute:在您的自定义单元格内进行练习,在您的案例中,单元格将是aCell 因此,从cellForRowAt indexPath调用此cell方法,并将我们的练习对象作为参数传递

e、 g.:aCell.configureCellWithexercise 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 

}
然后在exerciseCell中为开关创建一个动作方法

thisSwitch.addTarget(self, action: Selector("switchTriggered:"), forControlEvents: .ValueChanged );


func switchTriggered(sender: AnyObject) {

    let switch = sender as! UISwitch
    privateExercise.switchState = switch.isOn

}

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

非常感谢@Aby,这已经阻止了它们相互影响,但是如果我在tableview中向下滚动,然后向上滚动,开关将返回到关闭位置。我可能没有正确地处理私有变量,它不断给我错误关于没有分配一个exerciseName,所以我只是将名称初始化为。我想这是因为switchTriggered方法没有被识别。我在func中设置了一个打印开关,但它从未显示过。选择器样式正确吗?非常感谢@Aby,这已经阻止了它们相互影响,但是如果我在tableview中向下滚动,然后向上滚动,开关将返回到关闭位置。我可能没有正确地处理私有变量,它不断地给我关于no的错误
我没有指定exerciseName,所以我只是将名称初始化为。我想这是因为switchTriggered方法未被识别。我在func中设置了一个打印开关,但它从未显示过。选择器样式正确吗?