Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/17.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.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
Ios 如何防止单元格在另一个单元格中镜像按下按钮的操作?_Ios_Swift_Button_Colors_Cell - Fatal编程技术网

Ios 如何防止单元格在另一个单元格中镜像按下按钮的操作?

Ios 如何防止单元格在另一个单元格中镜像按下按钮的操作?,ios,swift,button,colors,cell,Ios,Swift,Button,Colors,Cell,我在tableview的单元格中有3个按钮,它们位于@iAction按钮集合中,因此当选择其中一个按钮时,它会将按钮颜色从蓝色变为红色,并取消选择之前按下的按钮,使其返回蓝色。执行这些操作时,代码工作正常 im的问题是,当在一个单元格中选择一个按钮时,另一个单元格中将选择完全相同的按钮,如下所示▼ 到目前为止,我尝试的方法不起作用,我认为可能有效的方法是在视图控制器中创建一个“@objc func”,但我不知道从我创建的方法到哪里去防止单元格中的“镜像” 我知道我已经接近解决办法了 提前感谢您提

我在tableview的单元格中有3个按钮,它们位于@iAction按钮集合中,因此当选择其中一个按钮时,它会将按钮颜色从蓝色变为红色,并取消选择之前按下的按钮,使其返回蓝色。执行这些操作时,代码工作正常

im的问题是,当在一个单元格中选择一个按钮时,另一个单元格中将选择完全相同的按钮,如下所示▼

到目前为止,我尝试的方法不起作用,我认为可能有效的方法是在视图控制器中创建一个“@objc func”,但我不知道从我创建的方法到哪里去防止单元格中的“镜像”

我知道我已经接近解决办法了 提前感谢您提供的任何帮助



您正在tableview中使用dequeuereusablecell。顾名思义,这些单元是可重用的。这意味着,当您滚动tableview时,单元格的某些UI方面的行为可能类似

为了防止这种情况,您总是需要一个“else”语句

sender.isSelected = true; do {
    self.lastSelectedButton.backgroundColor = UIColor.red
}

如果您不提供else语句,您很可能会在您的另一个单元格中看到另一个红色。

Hello,Evelyn!使用委派模式!:)

以下是一些有助于您继续前进的解释:

  • 创建一个模型来表示表视图内容

  • 我们可以使用什么样的模型来表示只选择一个按钮的状态?枚举可以表示(将其添加到单独的文件或控制器中):

    我们的表视图将显示这些枚举的数组,在控制器中,让我们添加一个实例变量来保存数据,并使用空数组初始化它:

    private var elements: [ButtonSelectionIdentity] = []
    
    让我们使用100个元素填充此数组,默认为选中的第一个按钮,在控制器viewDidLoad函数中,添加:

        for i in 0..<100 {
            elements.append(ButtonSelectionIdentity.first)
        }
    
    是的,在上述更改之后,它将不会编译,直到我们将更新方法添加到单元类:

    func update(with model: ButtonSelectionIdentity) {
        btn1.backgroundColor = .blue
        btn2.backgroundColor = .blue
        btn3.backgroundColor = .blue
    
        switch model {
        case .first:
            btn1.backgroundColor = .red
        case .second:
            btn2.backgroundColor = .red
        case .third:
            btn3.backgroundColor = .red
        }
    }
    
    编译并运行时,您将看到100个单元格的第一个正方形为红色

  • 允许将单元格动作连接到控制器

  • 删除控制器类中的
    buttonSelected
    方法,并删除Cell类中的
    btnTypeSelected
    方法,以便我们可以重新开始

    在这个阶段,我们有一个元素数组,这些元素在控制器内部的表视图中显示。控制器拥有它,因为它创建了它。单元格仅显示控制器的状态。所以,为了让我们的细胞更新,我们需要告诉控制器,我们正在更新。为此,我们可以使用委托模式。让我们创建一个单元委托协议来描述它

    单元格
    类文件中,在
    类单元格…
    之前,添加:

    protocol CellDelegate: class {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity)
    }
    
    weak var delegate: CellDelegate?
    
    这就是我们用来让控制器知道单元格中状态变化的委托。让我们向委托添加对单元格的弱引用。在
    单元格中
    ,添加:

    protocol CellDelegate: class {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity)
    }
    
    weak var delegate: CellDelegate?
    
    现在,使控制器符合
    CellDelegate
    协议。在控制器类中,添加:

    extension ViewController: CellDelegate {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
        }
    }
    
    现在我们将把它留空,稍后再完成

    现在,控制器可以是单元格的委托。让它成为唯一! 更新控制器的
    cellForRowAt
    方法,如下所示:

        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? Cell else { 
                return UITableViewCell() 
            }
    
            let model = elements[indexPath.row]
            cell.update(with: model)
            cell.delegate = self
    
            return cell
        }
    
    完成后,我们将控制器配置为单元的代理!让我们好好利用它吧

  • 当单元报告其状态更改时,使控制器更新模型

  • 在单元格中,分别连接每个按钮上的iActions:

    @IBAction func onFirstButtonTapped(_ sender: RoundButton) {
    }
    
    @IBAction func onSecondButtonTapped(_ sender: RoundButton) {
    }
    
    @IBAction func onThirdButtonTapped(_ sender: RoundButton) {
    }
    
    每当点击一个按钮时,我们希望我们的细胞告诉控制器一个状态变化,例如:

    @IBAction func onFirstButtonTapped(_ sender: RoundButton) {
        delegate?.onCellModelChange(cell: self, model: .first)
    }
    
    相应地实现其他两种方法

    在控制器中,让我们重新访问
    onCellModelChange
    方法。既然对单元格执行了操作,我们需要在
    elements
    数组中找到对应于该单元格的元素。为此,我们可以使用
    tableView
    -s
    -indepath(for:)
    方法:

    extension ViewController: CellDelegate {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
            guard let indexPath = tableView.indexPath(for: cell) else {
                return
            }
            print(indexPath)
        }
    }
    
    如果您运行应用程序,在这个阶段,您应该会看到与您按下按钮的单元格对应的IndExpath日志。 还不完全是我们需要的

    我们的表视图只显示一个单独的部分,所以我们可以忽略索引路径中的部分,只考虑一个行,它将与我们的元素索引相同。让我们使用以下索引更新数组中的值:

    extension ViewController: CellDelegate {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
            guard let indexPath = tableView.indexPath(for: cell) else {
                return
            }
            let index = indexPath.row
            elemets[index] = model
        }
    }
    
    现在如果你运行这个,你应该更新模型,但是单元格的状态不会马上更新。如果您将单元格移出屏幕并再次向后滚动,您仍然可以看到它正在工作

    最后一点是立即更新单元格。我们怎么能做到呢?让我们将更新后的模型放回单元:

    extension ViewController: CellDelegate {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
            guard let indexPath = tableView.indexPath(for: cell) else {
                return
            }
            let index = indexPath.row
            elemets[index] = model
            cell.update(with: model)
        }
    }
    
    这就是它! 我没有测试它,也没有编译它:)所以如果你发现任何打字错误,请告诉我:)
    干杯

    这已经在我的IBAciton func Btntypes牢房里了,但它不起作用。。。这就是为什么我试着把它放在视图控制器的objc func中,看看我是否得到了更好的结果,它是否有效!但是如果说它有一个类控制tableview中的单元格数量,比如说如果这个类被称为Labels,它替换了pick 1、2和3的文本,我怎么能转换它呢,很抱歉,我只是忘了在问题中问这个问题,因为我仍然在完成我的项目,但非常感谢所有的帮助,因为它与我所做的更改一起工作,直到我在cell.update(with:model)找到func cellForRowAt&cell.delegate=self如果希望单元格表示第一个/第二个/第三个按钮选择和一些标签,则应更新模型。Enum不再包含您需要的内容,因此,请创建一个同时包含Enum和label的结构
    struct CellModel{let buttonSelectionIdentity:buttonSelectionIdentity let labels:labels}
    在控制器中使用此结构代替
    元素
    extension ViewController: CellDelegate {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
            guard let indexPath = tableView.indexPath(for: cell) else {
                return
            }
            let index = indexPath.row
            elemets[index] = model
        }
    }
    
    extension ViewController: CellDelegate {
        func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
            guard let indexPath = tableView.indexPath(for: cell) else {
                return
            }
            let index = indexPath.row
            elemets[index] = model
            cell.update(with: model)
        }
    }