【问题标题】:UIButton inside custom UITableViewCell causes button to be selected in multiple cells自定义 UITableViewCell 中的 UIButton 导致在多个单元格中选择按钮
【发布时间】:2016-02-17 12:18:54
【问题描述】:

UITableView 的目标是在其旁边显示带有自定义样式复选框的名称。但不知何故,当我点击复选框时,UITableView 中的多个复选框被选中。

我已经从不同的问题搜索并实施了多种解决方案,但似乎没有一个有效。

自定义 UITableViewCell

import UIKit

class NameTableViewCell: UITableViewCell {

    var name = UILabel()

    let checkboxImage_unchecked = UIImage(named: "cellViewCheckbox_unchecked")
    let checkboxImage_checked = UIImage(named: "cellViewCheckbox_checked")

    let checkbox:UIButton

    weak var delegate:HandleCellInteractionDelegate?

    override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
        self.checkbox = UIButton(frame: CGRectMake(35, 16, self.checkboxImage_unchecked!.size.width/2, self.checkboxImage_unchecked!.size.height/2))
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.backgroundColor = UIColor.transparant()

        self.checkbox.setBackgroundImage(self.checkboxImage_unchecked, forState: .Normal)
        self.checkbox.setBackgroundImage(self.checkboxImage_checked, forState: .Selected)

        self.name = UILabel(frame: CGRectMake(97,18,200, 30))

        self.addSubview(self.name)
        self.addSubview(self.checkbox)
    }

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

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

    func checkboxPushed(sender:AnyObject){
        self.checkbox.selected = !self.checkbox.selected
        self.delegate?.didPressButton(self)            
    }

在协议中,我声明了一个方法 didPressButton 作为按下按钮时的回调(委托需要实现它)

协议

import UIKit

protocol HandleCellInteractionDelegate:class {
    func didPressButton(cell:NameTableViewCell)
}

视图控制器

import UIKit

class NameViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, HandleCellInteractionDelegate{

    var nameView:NameView {
        get {
            return self.view as! NameView
        }
    }

    var names:[Name]?
    var firstLetters:[String]?

    let cellIdentifier = "nameCell"

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        //self.view.backgroundColor = UIColor.darkSalmon()
    }

    override func loadView() {
        let bounds = UIScreen.mainScreen().bounds
        self.view = NameView(frame: bounds)
        if(NSUserDefaults.standardUserDefaults().objectForKey("gender") !== nil){
            self.loadJSON()
            self.getFirstLetters();
            self.nameView.tableView.delegate = self;
            self.nameView.tableView.dataSource = self;
            self.nameView.tableView.registerClass(NameTableViewCell.classForCoder(), forCellReuseIdentifier: "nameCell")
            self.nameView.tableView.separatorStyle = .None
            self.nameView.tableView.rowHeight = 66.5            }
    }

    func loadJSON(){
        let path = NSBundle.mainBundle().URLForResource("names", withExtension: "json")

        let jsonData = NSData(contentsOfURL: path!)


        self.names = NamesFactory.createFromJSONData(jsonData!, gender: NSUserDefaults.standardUserDefaults().integerForKey("gender"))
    }

    func getFirstLetters(){
        var previous:String = ""

        for name in self.names! {
            let firstLetter = String(name.name.characters.prefix(1))
            if firstLetter != previous {
                previous = firstLetter
                self.firstLetters?.append(firstLetter)
                print(firstLetter)
            }

        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return (self.names!.count)
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        return nameCellAtIndexPath(indexPath)
    }

    func nameCellAtIndexPath(indexPath:NSIndexPath) -> NameTableViewCell {
        let cell = self.nameView.tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! NameTableViewCell
        self.setNameForCell(cell, indexPath: indexPath)
        cell.delegate = self;
        cell.checkbox.addTarget(cell, action: "checkboxPushed:", forControlEvents: .TouchUpInside)
        return cell
    }

    func setNameForCell(cell:NameTableViewCell, indexPath:NSIndexPath) {
        let item = self.names![indexPath.row] as Name
        cell.name.text = item.name
    }

    func didPressButton(cell: NameTableViewCell) {
        print(cell)
    }

}

我做错了什么以及如何解决?

【问题讨论】:

  • 在单元格中添加目标,而不是在视图控制器中。多重选择是立即的,还是仅在您滚动时?
  • @Wain 我不知道它是否是即时的,因为它从不可见的单元格中选择按钮,但是当我滚动时,按钮的选中状态消失

标签: ios swift uitableview uibutton


【解决方案1】:

您必须保存复选框状态。向您的模型(名称)添加一个属性,例如 checkboxStatus。我希望您将拥有 indexpath.row。 在 nameCellAtIndexPath 这一行之后

cell.delegate = self;

这样设置标签

cell.tag = indexPath.row;

在委托方法中,

func didPressButton(cell: NameTableViewCell) {
    print(cell)
    let item = self.names![cell.tag] as Name
    item.checkboxstatus = cell.checkbox.selected
}

只有一个重要的变化,

func nameCellAtIndexPath(indexPath:NSIndexPath) -> NameTableViewCell {
    let cell = self.tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! NameTableViewCell
    self.setNameForCell(cell, indexPath: indexPath)
    cell.delegate = self;
    cell.tag = indexPath.row;
    cell.checkbox.addTarget(cell, action: "checkboxPushed:", forControlEvents: .TouchUpInside)
    let item = self.names![cell.tag] as Name
    cell.checkbox.selected = item.checkboxstatus
    return cell
}

干杯!

【讨论】:

    【解决方案2】:

    这是因为 UITableViewCell 正在被重用。

    您在按下复选框时更改了单元格,您需要在数据源模型中跟踪它。

    cellForRowAtIndexPath 中,您必须添加一个条件来检查该复选框是否被选中。然后相应地显示相应的视图。

    编辑: 在您的示例中,您需要检查 nameCellAtIndexPath 是否选中复选框,然后正确显示。

    【讨论】:

    • 感谢您的快速回复!我会尽快试试这个:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2010-11-05
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多