Detect When a Custom Cell Is Selected from Within The Cell Itself

Detect when a custom cell is selected from within the cell itself?

What you could do is listen for didSelectRowAtIndexPath on the UITableView, and then call a function in the cell. Here's an example:

class MyCustomCell: UITableViewCell {
func didSelect(indexPath: NSIndexPath) {
// perform some actions here
}
}

Then, in your didSelectRowAtIndexPath:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? MyCustomCell {
cell.didSelect(indexPath: indexPath)
}
}

How to find out which of the two custom cells is selected?

If there are two custom cells then there must be two Classes of UITableViewCell, you can simply differentiate the cell based on that .
See the code below :

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? MyCustomCell1 {
//Perform action here
} else if let cell = tableView.cellForRow(at: indexPath) as? MyCustomCell2 {
//Perform action here
}
}

UITableView Custom Cell button selects other buttons out of the main view?

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
}
}

Programmatically select itself inside UITableViewCell

Well, I found a solution for this, though I don't know if it's the best one.

First, I added a UITapGestureRecognizer to the UICollectionView inside my UITableViewCell, to override the component's one.

-(void)awakeFromNib
{
...
UITapGestureRecognizer *v_CollectionViewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onClickCollectionView)];
[self.m_CollectionView addGestureRecognizer:v_CollectionViewTap];
...
}

Second I created a block property to hold the code for the programatic selection of a row and created a method that calls this block, setting it as the action for the previously created UIGestureRecognizer.

typedef void (^OnClickTableViewCellBlock)();
@property (nonatomic, copy) OnClickTableViewCellBlock m_OnClickBlock;

Last, when I'm creating the UITableViewCell, in the tableView:cellForRowAtIndexPath: method, I pass a block that calls the tableview:didSelectRowAtIndexPath: one.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
v_Cell.m_OnClickBlock = ^void()
{
[tableView.delegate tableView:tableView didSelectRowAtIndexPath:indexPath];
};
...
}

Trying to get index of active cell from textField inside custom cell of UITableView in iOS

The way this is usually done, is to give the text field a tag equal to the indexPath.row, or if you have multiple sections, some mathematical combination of the section and row (like 1000*indexPathSection + indexPath.row).

Tableview selection hides my button within the tableview cell

Here is a solution. Give a tag number to the button.

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

var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell

// here is the redbutton

var redBtn = UIButton()
redBtn = UIButton(frame: CGRectMake(0, 0, 40, 40))
redBtn.backgroundColor = UIColor.redColor()
cell.contentView.addSubview(redBtn)
redBtn.tag = 101
//label text just added from an array

cell.textLabel?.textAlignment = NSTextAlignment.Center
cell.textLabel?.text = items[indexPath.row]

return cell
}

Now in didSelectRowAtIndex method add this.

func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {

var selectedCell = tableView.cellForRowAtIndexPath(indexPath) as UITableViewCell!

for subViews in selectedCell.contentView.subviews {

if subViews is UIButton && subViews.tag == 101 {
let button = subViews as! UIButton
selectedCell.bringSubviewToFront(button)
button.backgroundColor = UIColor.redColor()
}
}
}

Get the UITableViewCell indexPath using custom cells

since u are using the custom cell i think u need to handle selection also, because u are touching the button inside the custom cell not the cell itself therefore tableview delegate methods are not fired, better as i said in ur custom cell put a delegate method for example in ur custom cells

in your CellTypeOne.h add this

//@class CellTypeOne; //if u want t pass cell to controller
@protocol TouchDelegateForCell1 <NSObject> //this delegate is fired each time you clicked the cell
- (void)touchedTheCell:(UIButton *)button;
//- (void) touchedTheCell:(CellTypeOne *)cell; //if u want t send entire cell this may give error add `@class CellTypeOne;` at the beginning
@end

@interface CellTypeOne : UITableViewCell
{

}
@property(nonatomic, assign)id<TouchDelegateForCell1> delegate; //defining the delegate
- (IBAction)actionForFirstButton:(id)sender;
- (IBAction)actionForSecondButton:(id)sender;
- (IBAction)actionForThirdButton:(id)sender;
- (IBAction)actionForFourthButton:(id)sender;

in your CellTypeOne.m file

@synthesize delegate; //synthesize the delegate 

- (IBAction)actionForFirstButton:(UIButton *)sender
{
//add this condition to all the actions becz u need to get the index path of tapped cell contains the button
if([self.delegate respondsToSelector:@selector(touchedTheCell:)])
{
[self.delegate touchedTheCell:sender];
//or u can send the whole cell itself
//for example for passing the cell itself
//[self.delegate touchedTheCell:self]; //while at the defining the delegate u must change the sender type to - (void)touchedTheCell:(CellTypeOne *)myCell; if it shows any error in the defining of the delegate add "@class CellTypeOne;" above the defying the delegate
}
}

and in your ViewContainingMyTableView.h

 @interface ViewContainingMyTableView : UIViewController <UITableViewDelegate, UITableViewDataSource ,TouchDelegateForCell1> //confirms to custom delegate like table  delegates
{
UITableView *myTBV;
}

@property (retain, nonatomic) IBOutlet UITableView *myTBV;

@end

and in the ViewContainingMyTableView.m file

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//during the creating the custom cell
CellTypeOne *cell1 = [self.aTableView dequeueReusableCellWithIdentifier:@"cell"];
if(cell1 == nil)
{
cell1 = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
}
cell.delegate = self; //should set the delegate to self otherwise delegate methods does not called this step is important
}

//now implement the delegate method , in this method u can get the indexpath of selected cell

- (void)touchedTheCell:(UIButton *)button
{
NSIndexPath *indexPath = [self.aTableView indexPathForCell:(UITableViewCell *)button.superview];
NSLog(@"%@",indexPath.description);

}
/* if u pass the cell itself then the delegate method would be like below
- (void)touchedTheCell:(CellTypeOne *)myCell
{
NSIndexPath *indexPath = [self.aTableView indexPathForCell:myCell];//directly get the cell's index path
//now by using the tag or properties, whatever u can access the contents of the cell
UIButton *myButton = [myCell.contentView viewWithTag:1000]; //get the button
//... u can access all the contents in cell
}
*/

in your case, this is for first button in the cell, add the delegate methods for each buttons having different functions, repeat above procedure for another buttons in the cell

hope u get this :) hapy coding



Related Topics



Leave a reply



Submit