简体   繁体   中英

Swift - Adding a checkbox to every cell in the tableView

I've already made a table view which allows the user to add tasks to the table view, but now I need to add a checkbox in front of each task, so that the user can select which tasks she/he wants to send to an other viewController.

After I googled it, I realized that there is no checkBox or radioButton in swift, I should create my own "boxChecked.png" and "boxUnchecked.png",

Here is a piece of my code which gives me an error:

if (selectedIndex == indexPath) {
    cell.radioButton?.setImage(UIImage(named: "boxChecked"),forState:UIControlState.Normal)
} else {
    cell.radioButton?.setImage(UIImage(named: "boxUnchecked"),forState:UIControlState.Normal)
}

and the error it gives me is:

'UITableViewCell?' does not have a member named 'radiobutton'

even though I tried creating a class named TableViewCell which is a subclass of UITableViewCell, and declared the variable radioButton in it like:

 @IBOutlet weak var radioButton: UIButton!

but it still didn't work.

Here is the code of func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) :

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

        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")




        if (selectedIndex == indexPath) {
            cell.radioButton?.setImage(UIImage(named: "boxChecked"),forState:UIControlState.Normal)
        } else {
            cell.radioButton?.setImage(UIImage(named: "boxUnchecked"),forState:UIControlState.Normal)
        }






        cell.textLabel?.textAlignment = .Right
        cell.detailTextLabel?.textAlignment = .Left

      cell.textLabel?.text = taskMgr.tasks[indexPath.row].name

        cell.detailTextLabel?.text = taskMgr.tasks[indexPath.row].score







        return cell

        //let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Default")
       // cell.textLabel?.text = taskMgr.tasks[indexPath.row].name
       // cell.detailTextLabel?.text = taskMgr.tasks[indexPath.row].desc
       //return cell

    }

Try this code:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cellIdentifier = "cell"
    var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? TableViewCell
    if cell == nil {
        cell = TableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: cellIdentifier)

    }
    if (selectedIndex == indexPath) {
        cell!.radioButton?.setImage(UIImage(named: "boxChecked"),forState:UIControlState.Normal)
    } else {
        cell!.radioButton?.setImage(UIImage(named: "boxUnchecked"),forState:UIControlState.Normal)
    }

    cell!.textLabel?.textAlignment = .Right
    cell!.detailTextLabel?.textAlignment = .Left

    cell!.textLabel?.text = taskMgr.tasks[indexPath.row].name
    cell!.detailTextLabel?.text = taskMgr.tasks[indexPath.row].score
    return cell!
}

You should instantiatie your custom table view cell like this if you're using Interface Builder:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCellWithIdentifier("IdentifierInInterfaceBuilder") as? MyCustomTableViewCell else {
        return UITableViewCell()
    }

    return cell
}

Set up your cell in IB like this:

自定义单元格

标识符


I think your approach might be more difficult than necessary. When you have a UITableViewCell the standard (not custom ones) allow for text and an image. If you set the image through Interface Builder (or programmatically) you can set a normal and a highlighted image value. This will use the selected image whenever the cell is selected and the other when it isn't.

This also means now that a regular selection action will be enough, making the whole table view cell a hotspot and you can very simply get the selected cells and the events for selecting and unselecting through the built-in delegates and functions.

For more complex approaches not falling within the possibilities of a Plain UITableViewCell you can use the highlighted value for a UIImageView and change it after either selecting or when you load it at first.

class ExampleTableViewCell: UITableViewCell {
    @IBOutlet var checkMark: UIImageView?

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

        checkMark?.highlighted = selected
    }
}

Do you see how little code it requires and how it just works with the flow of the way the UITableView works?

You have a UITableView . It uses cells to display content. There is one built-in default implementation of a cell: UITableViewCell . In order to customize UITableViewCell appearance, we create custom cells like you did with the TableViewCell class. Bring it back if you deleted it.

UITableView reuses cells for efficiency. When the cell goes off screen, it is saved, and when the table view needs the same kind of cell later, it doesn't recreate it every time. It takes it from its cache (if it is not empty).

There may be several different kinds of cells in a table view (eg user info cell, tasks cells, etc.). In order to understand, what kind of cell the table view should create/get from cache, reuseIdentifer is used. reuseIdentifer denotes a kind of cell. So, there should be some way to tell the tableView , that when we request a "RadioButtonCell" (for instance), we want it to create a cell with class TableViewCell (your custom subclass).

There are several ways to do that. It can be done via storyboards, it can be done through code. If your cell has a xib (interface file) associated with it, you can do it using

tableView.registerNib(UINib(nibName: "TableViewCell", bundle: nil)), forCellReuseIdentifier: "RadioButtonCell")

If you didn't create an interface file for it, you can do it using

tableView.registerClass(..., forCellReuseIdentifier: ...)

method.

You can register nibs once (for instance, inside viewDidLoad). Then later in cellForRowAtIndexPath you do:

var cell: TableViewCell = tableView.dequeueReusableCellWithIdentifier("RadioButtonCell)

and customize this cell as you did in your question.

Did you changed the type of the UITableViewCell using the interface builder to your custom UITableViewCell

Select your cell > Select the Identity Inspector in the right pane > change the class to your custom UITableViewCell class name.

You need also to connect the check button view with the outlet in your custom class.

You also need to add 2 UILabels one for the title and one for the details and connect them too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM