On my custom tableviewcell I have a button which the user can press which toggles between selected and unselected. This is just a simple UIButton, this button is contained with my customtableviewcell as an outlet.
import UIKit
class CustomCellAssessment: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var dateTaken: UILabel!
#IBOutlet weak var id: UILabel!
#IBOutlet weak var score: UILabel!
#IBOutlet weak var button: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func selectButton(_ sender: UIButton) {
if sender.isSelected{
sender.isSelected = false
}else{
sender.isSelected = true
}
}
}
The strange thing is, when I press a button on say the first cell it then selects a button 8 cells down on another cell (out of the view) in the same tableview. Each cell has its own button but it is as if using dequeReusableCell is causing the system to behave this way. Why is it doing this and is it to do with the way that UIbuttons work on tableviewcells?
Thanks
Each cell has its own button but it is as if using dequeReusableCell is causing the system to behave this way.
Wrong. UITableViewCells are reusable, so if your tableView has 8 cells visible, when loading the 9th, the cell nr 1 will be reused.
Solution: You need to keep track of the state of your cells. When the method cellForRowAtIndexPath is called, you need to configure the cell from scratch.
You could have in your ViewController an small array containing the state of the cells:
var cellsState: [CellState]
and store there the selected state for each indexPath. Then in the cellForRowAtIndexPath, you configure the cell with the state.
cell.selected = self.cellsState[indexPath.row].selected
So, an overview of I would do is:
1 - On the cellForRowAtIndexPath, I would set
cell.button.tag = indexPath.row
cell.selected = cellsState[indexPath.row].selected
2 - Move the IBAction to your ViewController or TableViewController
3 - When the click method is called, update the selected state of the cell
self.cellsState[sender.tag].selected = true
Remember to always configure the whole cell at cellForRowAtIndexPath
Edit:
import UIKit
struct CellState {
var selected:Bool
init(){
selected = false
}
}
class MyCell: UITableViewCell {
#IBOutlet weak var button: UIButton!
override func awakeFromNib() {
self.button.setTitleColor(.red, for: .selected)
self.button.setTitleColor(.black, for: .normal)
}
}
class ViewController: UIViewController, UITableViewDataSource {
var cellsState:[CellState] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Add state for 5 cells.
for _ in 0...5 {
self.cellsState.append(CellState())
}
}
#IBAction func didClick(_ sender: UIButton) {
self.cellsState[sender.tag].selected = true
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsState.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MyCell
cell.button.isSelected = self.cellsState[indexPath.row].selected
cell.button.tag = indexPath.row
return cell
}
}
When you tap the button, you're setting the selected state of the button. When the cell gets reused, the button is still selected - you're not doing anything to reset or update that state.
If button selection is separate to table cell selection, then you'll need to keep track of the index path(s) of the selected buttons as part of your data model and then update the selected state of the button in tableView(_: cellForRowAt:).
A table view will only create as many cells as it needs to display a screen-and-a-bits worth of information. After that, cells are reused. If a cell scrolls off the top of the screen, the table view puts it in a reuse queue, then when it needs to display a new row at the bottom as you scroll, it pulls that out of the queue and gives it to you in tableView(_: cellForRowAt:).
The cell you get here will be exactly the same as the one you used 8 or so rows earlier, and it's up to you to configure it completely. You can do that in cellForRow, and you also have an opportunity in the cell itself by implementing prepareForReuse, which is called just before the cell is dequeued.
In your tableView(_: cellForRowAt:) take action for button click and add target
cell.button.addTarget(self, action: #selector(self.selectedButton), for: .touchUpInside)
At the target method use below lines to get indexPath
func selectedButton(sender: UIButton){
let hitPoint: CGPoint = sender.convert(CGPoint.zero, to: self.tableView)
let indexPath: NSIndexPath = self.tableView.indexPathForRow(at: hitPoint)! as NSIndexPath
}
Then do your stuff by using that indexPath.
Actually your method can not find in which indexPath button is clicked that's why not working your desired button.
One way to approach your problem is as follow
1. First create a protocol to know when button is clicked
protocol MyCellDelegate: class {
func cellButtonClicked(_ indexPath: IndexPath)
}
2. Now in your cell class, you could do something like following
class MyCell: UITableViewCell {
var indexPath: IndexPath?
weak var cellButtonDelegate: MyCellDelegate?
func configureCell(with value: String, atIndexPath indexPath: IndexPath, selected: [IndexPath]) {
self.indexPath = indexPath //set the indexPath
self.textLabel?.text = value
if selected.contains(indexPath) {
//this one is selected so do the stuff
//here we will chnage only the background color
backgroundColor = .red
self.textLabel?.textColor = .white
} else {
//unselected
backgroundColor = .white
self.textLabel?.textColor = .red
}
}
#IBAction func buttonClicked(_ sender: UIButton) {
guard let delegate = cellButtonDelegate, let indexPath = indexPath else { return }
delegate.cellButtonClicked(indexPath)
}
}
3. Now in your controller. I'm using UItableViewController here
class TheTableViewController: UITableViewController, MyCellDelegate {
let cellData = ["cell1","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4"]
var selectedIndexpaths = [IndexPath]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellData.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 55.0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
cell.cellButtonDelegate = self
cell.configureCell(with: cellData[indexPath.row], atIndexPath: indexPath, selected: selectedIndexpaths)
return cell
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30.0
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! MyCell
cell.buttonClicked(UIButton())
}
func cellButtonClicked(_ indexPath: IndexPath) {
if selectedIndexpaths.contains(indexPath) {
//this means cell has already selected state
//now we will toggle the state here from selected to unselected by removing indexPath
if let index = selectedIndexpaths.index(of: indexPath) {
selectedIndexpaths.remove(at: index)
}
} else {
//this is new selection so add it
selectedIndexpaths.append(indexPath)
}
tableView.reloadData()
}
}
Related
I was wondering if there any possible way to create a table view with this style:
I have a dictionary contains title and image values, I need to create a cell one Image-Right / Title-Left and next vice versa. How can achieve something like this?
You can do it by setAffineTransform in this way:
• build up your tableView with one prototype cell that has an image in left and a label in right
• then do this:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellIdentifier", for: indexPath) as! YourTableViewCell
if (indexPath.row % 2 == 0) {
cell.contentView.layer.setAffineTransform(CGAffineTransform(scaleX: -1, y: 1))
cell.YourImage.layer.setAffineTransform(CGAffineTransform(scaleX: -1, y: 1))
cell.YourLabel.layer.setAffineTransform(CGAffineTransform(scaleX: -1, y: 1))
}
// do what ever you want ...
return cell
}
also the best solution is defining 2 prototype cells but in your case this is a tricky and fast way to achieve your goal.
Yes, you can use a table view to achieve your requirement. you will need to follow the following steps.
Method 1:
Create two table view cell XIB's one with left side label and right side image, the second one is with left side image and right side image.
Keep same class of both the XIB's you have created but with different identifiers.
In your Table view cellForRowAtIndexPath method implement following logic.
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datasourceArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(indexPath.row % 0 == 0) {
let cell = tableView.dequeueReusableCell(withIdentifier: "RightLabelTableViewCell", for: indexPath) as! CustomTablViewCell
cell.model = datasourceArray[indexPath.row]
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "LeftLabelTableViewCell", for: indexPath) as! CustomTablViewCell
cell.model = datasourceArray[indexPath.row]
return cell
}
}
}
Note: You can use one class for TableViewCell with a different
identifier and design your xib's accordingly.
Method 2:
Flip your table view cell's content view in a such a way that they will swap in your UI.
add the following code into your cellForRowAtIndexPath and also add else part of it because cell for a row may behave weirdly because of dequeing:
extension UIView {
/// Flip view horizontally.
func flipX() {
transform = CGAffineTransform(scaleX: -transform.a, y: transform.d)
}
}
Usage:
cell.contentView.flipX()
cell.yourImage.flipX()
cell.youImageName.flipX()
Don't forget to add else part in cellForRowAt method.
There are actually many ways of doing this:
Create 2 cells. Have 2 cells like OddTableViewCell and EvenTableViewCell. You can choose with index path which to use in cellForRow method like:
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(indexPath.row%0 == 0) {
let cell = tableView.dequeueReusableCell(withIdentifier: "EvenTableViewCell", for: indexPath) as! EvenTableViewCell
cell.model = dataArray[indexPath.row]
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "OddTableViewCell", for: indexPath) as! OddTableViewCell
cell.model = dataArray[indexPath.row]
return cell
}
}
}
Have a single cell but duplicate views so you have 2 labels and 2 image views. Then hide them as you need to:
class MyCell: UITableViewCell {
#IBOutlet private var leftImageView: UIImageView?
#IBOutlet private var rightImageView: UIImageView?
#IBOutlet private var leftLabel: UILabel?
#IBOutlet private var rightLabel: UILabel?
var userImage: UIImage? {
didSet {
refresh()
}
}
var userName: String? {
didSet {
refresh()
}
}
var imageOnLeft: Bool = false {
didSet {
refresh()
}
}
func refresh() {
leftImageView?.image = imageOnLeft ? userImage : nil
leftImageView?.isHidden = !imageOnLeft
rightImageView?.image = imageOnLeft ? nil : userImage
rightImageView?.isHidden = imageOnLeft
leftLabel?.text = imageOnLeft ? nil : userName
leftLabel?.isHidden = imageOnLeft
rightLabel?.text = imageOnLeft ? userName : nil
rightLabel?.isHidden = !imageOnLeft
}
}
Have a single cell with stack view. Add a label and image view onto the stack view. You can change order of items in stack view. Some promising answer can be found here. The rest should be pretty similar to the second solution.
(4.) Also you could just use a collection view and have a label cell and an image cell.
Create one cell with 2 image and 2 label left and right
when you went to left side image that time hide right side image same as in label.
cell
import UIKit
class TestTableViewCell: UITableViewCell {
#IBOutlet weak var lbl_left: UILabel!
#IBOutlet weak var lbl_right: UILabel!
#IBOutlet weak var img_right: UIImageView!
#IBOutlet weak var img_left: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func configure_cell(left:Bool)
{
if left{
img_left.isHidden = true
img_right.isHidden = false
lbl_left.isHidden = false
lbl_right.isHidden = true
self.img_right.image = UIImage(named: "testimg")
}else{
img_left.isHidden = false
img_right.isHidden = true
lbl_left.isHidden = true
lbl_right.isHidden = false
self.img_left.image = UIImage(named: "testimg")
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
ViewController
extension ViewController:UITableViewDataSource,UITableViewDelegate
{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 120
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 120
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as? TestTableViewCell
if (indexPath.row + 1) % 2 == 0 {
cell?.configure_cell(left: true)
} else {
cell?.configure_cell(left: false)
}
return cell!
}
}
I need to detect if the button has been clicked in the UITableViewController
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let LikesBtn = cell.viewWithTag(7) as! UIButton
}
The easiest and most efficient way in Swift is a callback closure.
Subclass UITableViewCell, the viewWithTag way to identify UI elements is outdated.
Set the class of the custom cell to the name of the subclass and set the identifier to ButtonCellIdentifier in Interface Builder.
Add a callback property.
Add an action and connect the button to the action.
class ButtonCell: UITableViewCell {
var callback : (() -> Void)?
#IBAction func buttonPressed(_ sender : UIButton) {
callback?()
}
}
In cellForRow assign the callback to the custom cell.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ButtonCellIdentifier", for: indexPath) as! ButtonCell
cell.callback = {
print("Button pressed", indexPath)
}
return cell
}
When the button is pressed the callback is called. The index path is captured.
Edit
There is a caveat if cells can be added or removed. In this case pass the UITableViewCell instance as parameter and get the index path from there
class ButtonCell: UITableViewCell {
var callback : ((UITableViewCell) -> Void)?
#IBAction func buttonPressed(_ sender : UIButton) {
callback?(self)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ButtonCellIdentifier", for: indexPath) as! ButtonCell
let item = dataSourceArray[indexPath.row]
// do something with item
cell.callback = { cell in
let actualIndexPath = tableView.indexPath(for: cell)!
print("Button pressed", actualIndexPath)
}
return cell
}
If even the section can change, well, then protocol/delegate may be more efficient.
First step:
Make Subclass for your custom UITableViewCell, also register protocol.
Something like this:
protocol MyTableViewCellDelegate: class {
func onButtonPressed(_ sender: UIButton, indexPath: IndexPath)
}
class MyTableViewCell: UITableViewCell {
#IBOutlet var cellButton: UIButton!
var cellIndexPath: IndexPath!
weak var delegate: MyTableViewCellDelegate!
override func awakeFromNib() {
super.awakeFromNib()
cellButton.addTarget(self, action: #selector(self.onButton(_:)), for: .touchUpInside)
}
func onButton(_ sender: UIButton) {
delegate.onButtonPressed(sender, indexPath: cellIndexPath)
}
}
In your TableViewController, make sure it conform to your just created protocol "MyTableViewCellDelegate".
Look at the code below for better understanding.
class MyTableViewController: UITableViewController, MyTableViewCellDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as? MyTableViewCell {
cell.cellIndexPath = indexPath
cell.delegate = self
return cell
} else {
print("Something wrong. Check your cell idetifier or cell subclass")
return UITableViewCell()
}
}
func onButtonPressed(_ sender: UIButton, indexPath: IndexPath) {
print("DID PRESSED BUTTON WITH TAG = \(sender.tag) AT INDEX PATH = \(indexPath)")
}
}
Here is what I use:
First initialize the button as an Outlet and its action on your TableViewCell
class MainViewCell: UITableViewCell {
#IBOutlet weak var testButton: UIButton!
#IBAction func testBClicked(_ sender: UIButton) {
let tag = sender.tag //with this you can get which button was clicked
}
}
Then in you Main Controller in the cellForRow function just initialize the tag of the button like this:
class MainController: UIViewController, UITableViewDelegate, UITableViewDataSource, {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MainViewCell
cell.testButton.tag = indexPath.row
return cell
}
}
I have images in my tableView cells, so I have set the cell selectionStyle to None, in order to avoid the cells highlighting when they're selected.
I'm now trying to implement editing into the tableView, allowing users to select multiple cells, filling in the checkmark cirle on the left of the cells. However, this doesn't seem to work with a selectionStyle of None - the circle just remains unfilled.
Is there any way to solve this?
Thanks?
If you can't select the cells directly you can place a uibutton in the cell and recognize in which cell the button that was tapped was.To do that you can set the button tag to equal the indexPath.row inside the cellForRowAtIndexPath method.
The code below prints the correct row number. Hope this helps.
class MyTableViewCell: UITableViewCell {
#IBOutlet weak var onButton: UIButton!
}
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func buttonClicked(sender:UIButton) {
let buttonRow = sender.tag
print(buttonRow)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! MyTableViewCell
cell.onButton.tag = indexPath.row
cell.onButton.addTarget(self, action: #selector(ViewController.buttonClicked(sender:)), for: .touchUpInside)
return cell
}}
How to change tableView textLabel when different buttons is clicked. I have two action buttons brandButton and profileButton, what I want to happen is when I click brandButton brandInformation will show up to the tableView textLabel, and when I click profileButton profileInformation will show up.
import UIKit
class StreamDetailController: UITableViewDataSource, UITableViewDelegate{
#IBOutlet weak var tableViewController: UITableView!
var brandInformation = ["Hat:","Top:","Pants:","Shoes"]
var profileInformation = ["tim", "master"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return brandInformation.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewController.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = brandInformation[indexPath.row]
return cell
#IBAction func brandButton(_ sender: Any) {
}
#IBAction func profileButton(_ sender: Any) {
}
Note:
in this line:
#IBOutlet weak var tableViewController: UITableView!
the variable is wrong and can be confusing. the tableViewController should be renamed to tableView
1. Solution
add a class var to hold which view you like to see and chenge it with the buttons. then call reloadData on the table to refresh the content:
cell.textLabel?.text = brandInformation[indexPath.row]
to
var isShowBrand = true
// [...]
if isShowBrand {
cell.textLabel?.text = brandInformation[indexPath.row]
} else {
cell.textLabel?.text = profileInformation[indexPath.row]
}
and also for the rowcount (you can also use the ternary operator:
return isShowBrand ? brandInformation.count : profileInformation.count
(if you like to save it per cell then you need to save this info similar how you save the cell data var showBrand = [true, false] - but check that all 3 arrays have the same count of items to avoid index out of bounds errors)
2. Solution
just make a additional array tableData and you set in the buttons the array you need to see. and all data populating is done with the tableData array (you need to change all brandInformation to tableData)
var tableData = [String]()
// [...]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableViewController.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = tableData[indexPath.row]
return cell
}
// [...]
#IBAction func brandButton(_ sender: Any){
tableData = brandInformation
tableViewController.reloadData()
}
#IBAction func profileButton(_ sender: Any){
tableData = profileInformation
tableViewController.reloadData()
}
I made an app with UITableView. I want to show a tick mark in the left when cell is touched, and to be hidden when again is touched. I used some code and It's not showing as I wanted. The tick is showing on the right not on the left of screen.
This is how I want to make:
This is how it is:
And here is code that I used:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
self.myTableView.allowsMultipleSelection = true
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.Checkmark
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = UITableViewCellAccessoryType.None
}
In conclusion, first problem is that the tick is showing on the right of the cell and not on the left. And the other problem, it won't untick (hide when cell is pressed again)
Thanks.
Try this
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "DhikrTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! GoalsTableViewCell
cell.tickButton.addTarget(self, action: #selector(GoalsViewController.toggleSelcted(_:)), forControlEvents: UIControlEvents.TouchUpInside)
cell.tickButton.tag = indexPath.row
// Fetches the appropriate meal for the data source layout.
let workout = workouts[indexPath.row]
let number = numbers[indexPath.row]
if workout.isSelected {
cell.tickButton.setImage(UIImage(named: "Ticked Button"), forState: UIControlState.Normal)
} else {
cell.tickButton.setImage(UIImage(named: "Tick Button"), forState: UIControlState.Normal)
}
cell.nameLabel.text = workout.name
cell.numberLabel.text = number.number
return cell
}
func toggleSelcted(button: UIButton) {
let workout = workouts[button.tag]
workout.isSelected = !workout.isSelected
myTableView.reloadData()
}
To achieve this behavior with default UITableViewCell, you may need to set table view to edit mode.
Try the following code in your viewDidLoad.
self.tableView.allowsMultipleSelectionDuringEditing = true
self.tableView.setEditing(true, animated: false)
This will show tick mark on the left side, and also this will untick (hide) when cell is pressed again.
Edited:
If you need more customization, Create a custom table view cell and handle the selection/tick mark manually.
This will be your cell.swift.
class CustomCell: UITableViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tickImageView: UIImageView!
//Handles the cell selected state
var checked: Bool! {
didSet {
if (self.checked == true) {
self.tickImageView.image = UIImage(named: "CheckBox-Selected")
}else{
self.tickImageView.image = UIImage(named: "CheckBox-Normal")
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
checked = false
self.layoutMargins = UIEdgeInsetsZero
self.separatorInset = UIEdgeInsetsZero
}
The datasource array is,
let list = ["Title 1", "Title 2", "Title 2", "Title 4"]
The view controller didLoad will be like
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
listView.registerNib(UINib(nibName: "OptionsSelectionCell", bundle: nil), forCellReuseIdentifier: "SelectionCell")
}
The view controller table delegate methods will be like,
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SelectionCell") as! OptionsSelectionCell
cell.titleLabel.text = list[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! OptionsSelectionCell
cell.checked = !cell.checked
}
}