get section number and row number on custom cells button click? - iphone

i have tableview with custom cell.the table is divided in many section and rows.i have a custom button on cell. now i want to get section number and row number when i click on that button.?
any idea regarding this

You'll need to implement a UIControl event-handling method on your view controller, and set that as the handler for all your buttons. i.e. inside your -tableView:cellForRowAtIndexPath: function you would do something like:
[theCell.button addTarget: self
action: #selector(buttonPressed:withEvent:)
forControlEvents: UIControlEventTouchUpInside];
Then your event handler would look like this:
- (void) buttonPressed: (id) sender withEvent: (UIEvent *) event
{
UITouch * touch = [[event touches] anyObject];
CGPoint location = [touch locationInView: self.tableView];
NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint: location];
/* indexPath contains the index of the row containing the button */
/* do whatever it is you need to do with the row data now */
}

A few thoughts:
You can iterate through the button's superview hierarchy until you find a UITableViewCell, then call - (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell on the UITableView.
- (void)buttonClicked:(id)sender {
UIView *button = sender;
for (UIView *parent = [button superview]; parent != nil; parent = [parent superview]) {
if ([parent isKindOfClass: [UITableViewCell class]]) {
UITableViewCell *cell = (UITableViewCell *) parent;
NSIndexPath *path = [self.tableView indexPathForCell: cell];
// now use the index path
break; // for
}
}
}
You can alternately use the tag of the button to store an index referencing the row. This only holds a single integer, so it makes the most sense when you have a single section, or when you are managing your rows as a flat list.
You can alternately subclass UITableViewCell to encapsulate the button. Your UITableViewCell could respond to the button events and rebroadcast an event to its own delegate, passing self. The event delegate can then call - (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell on the UITableView to get the index path.

The following method is called when you select a cell in your tableView:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
to access the section number: int section = indexPath.section;
to access the row number (within the correct section): int row = indexPath.row;

The UITableView can convert a CGPoint coordinate into an indexPath:
-(NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point

Add can instance variable of your UITableViewCell subclassTo store the index path of the cell:
NSIndexPath *myIndexPath;
When you create the cell in:
cellForIndexPath:
pass in the indexpath to the newly created/recycled cell.
Now when you press the button, just read the indexpath from the ivar of your cell.

Related

How to know the section number on button click of Tableview cell in a UITableView? [duplicate]

This question already has answers here:
How to know the UITableview row number
(10 answers)
Closed 9 years ago.
I have a UITableView for which I have created a custom UITableViewCell. Each row in tableview has a button. I want to know the section number on click of a button, so that I would know that from which section button has been clicked. I have already tried few things found on stack but nothing is working.
UIButton *b = sender;
NSIndexPath *path = [NSIndexPath indexPathForRow:b.tag inSection:0];
NSLog(#"Row %d - Section : %d", path.row, path.section);
Don't know what you've tried, but i might do something like this. Doing some pseudocode from memory, here.
- (void)buttonClicked:(id)sender {
CGPoint buttonOrigin = [sender frame].origin;
// this converts the coordinate system of the origin from the button's superview to the table view's coordinate system.
CGPoint originInTableView = [self.tableView convertPoint:buttonOrigin fromView:[sender superview];
// gets the row corresponding to the converted point
NSIndexPath rowIndexPath = [self.tableView indexPathForRowAtPoint:originInTableView];
NSInteger section = [rowIndexPath section];
}
If I'm thinking clearly, this gives you flexibility in case the button's not directly inside the UITableView cell. Say, if you've nested inside some intermediary view.
Sadly, there doesn't seem to be an iOS equivalent of NSTableView's rowForView:
Create a handler for button click and add it in tableView:cellForRowAtIndexPath: method
- (void)buttonPressed:(UIButton *)button{
UITableViewCell *cell = button.superView.superView;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
//Now you have indexPath of the cell
//do your stuff here
}
When you create your custom UITableViewCell in cellForRowAtIndexPath you should pass it its section as a parameter. It could look like:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
if (!cell)
{
cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier" section:indexPath.section] autorelease];
}
return cell;
}
Now your cell knows its section and you can use it when performing click method in MyCustomCell class
Try this,
First assign section as a tag to button also add target on button in cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...
[cell.btnSample setTag:indexPath.section];
[cell.btnSample addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
...
}
Get Section as tag from sender of IBAction you defined (buttonClicked here).
-(IBAction)buttonClicked:(id)sender
{
NSLog(#"Section: %d",[sender tag]);
}

Button inside UITableViewCell - how do i find out what cell it's inside?

I have a button inside every cell of my UITableView, but when the button is triggered, I want to find out which cell it's inside. I could use a tag, or subclass the button and add a indexPath to it, but then the problem comes when I'm deleting or adding cells and I have to keep up with updating all those buttons. Is there another way people can think of doing this well?
UITableViewCell * cell = (UITableViewCell*) button.superview;
NSIndexPath * indexpath = [myTableView indexPathForCell:cell]
Use UITableView's indexPathForCell: method. It takes a cell, and gives you the index path for the cell.
try this
- (void) buttonAction:(id)sender{
UIButton *buttonInCell = (UIButton *)sender;
NSIndexPath *indexPathOfCell = [self.yourTable indexPathForCell:
(UITableViewCell *)[[buttonInCell superview] superview]];
}
where the buttonInCell hold the sender Button and indexPathOfCell holds the indexPath value of the Cell that has the Particular Button from which the action has been triggered
the above way may not work with iOS 7
update
- (void)buttonAction:(id)sender {
UIButton *buttonInCell = (UIButton *)sender;
CGPoint center= buttonInCell.center;
CGPoint rootViewPoint = [buttonInCell.superview convertPoint:center toView:self.yourTableView];
NSIndexPath *indexPath = [self.yourTableView indexPathForRowAtPoint:rootViewPoint];
NSLog(#"%#",indexPath);
}

How to get Indexpath of cell in UITableView while clicking on Custom accessory Button?

I have UITableView.In that i have created custom cell with accessory button.Now by clicking on accessory button i want to create another view with edit cell functionality.For that how do i find the index path of that cell?and how do i pass the vales of that cell?
How do i call following method:
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
First thing to note here is that when you use custom accessoryView in a cell then the tableView:accessoryButtonTappedForRowWithIndexPath: delegate method would not be called. You have to add some target/action to the button you are adding as the custom accessory and handle the tap action yourself. You should add the custom accessory something like this,
UIButton *accessory = ...;
[accessory addTarget:self action:#selector(onCustomAccessoryTapped:) forControlEvents:UIControlEventTouchUpInside];
...
cell.accessoryView = accessory;
And in the onCustomAccessoryTapped: method you have to get the index path like this,
- (void)onCustomAccessoryTapped:(UIButton *)sender {
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
// Now you can do the following
[self tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath];
// Or you can do something else here to handle the action
}
The indexPath is passed as the second parameter to the method.
using "indexPathForCell" works as mentioned by emptystack
[yourViewController.tableView indexPathForCell: cell];
In addition if you are using tableview and a Search View, in your controller make sure to use searchDisplayController
NSIndexPath *indexPath;
NSDictionary *campaignMember;
if(self.searchDisplayController.isActive) {
indexPath = [[self.searchDisplayController searchResultsTableView] indexPathForCell: cell];
campaignMember = [self.filterResults objectAtIndex:indexPath.row];
} else {
indexPath = [self.tableView indexPathForCell: cell];
campaignMember = [self.dataRows objectAtIndex:indexPath.row];
}
NSString *id = [campaignMember objectForKey:#"Id"];
In my case "campaignMember" is a person object and I needed to get its id. "self.dataRows" is an array that holds main table data where as "self.filterResults" contains a subset or search/filter results of all the data based on search/filter criteria.

How to get indexPath.row/path When I click the Switch in a row?

I create tow or more custom cell
each cell has a switch inside
How can I know which switch in the row I click
ex.I click the switch in row 3,than It will return indexPath.row = 3
and also the switch status is on or off ?
which void I should put in ?
I know there is a way can get indexpath return by:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
But I don't want to touch the row,just the switch ...
Oh I do some research but it just be a little different
How can keep track of the index path of a button in a tableview cell?
any ideas ?
I wish I can post my screen shot,but not I am a new user
the system doesn't allow me to do this
When you create the switch, set up a target and action for it:
[mySwitch addTarget:self action:#selector(switchToggled:) forControlEvents:UIControlEventValueChanged];
Here, the target self is your UITableViewController, in which you'll need to implement the method (void) switchToggled:(id)sender to handle the control event. The switch will automatically send itself to the switchToggled method as the sender when it is toggled. Like this (modified from the UIButton example you linked):
- (void)switchToggled:(id)sender {
UISwitch *theSwitch = (UISwitch *)sender;
UITableViewCell *cell = (UITableViewCell *)theSwitch.superview;
UITableView *tableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
if(theSwitch.on) {
// switch turned on
}
else {
// switch turned off
}
}
When button is created
button.tag = [indexPath row]
When button is selected, pull the row out of the tag
int myRow = [(UIButton *)sender tag];

How can I keep track of the index path of a button in a table view cell?

I have a table view where each cell has a button accessory view. The table is managed by a fetched results controller and is frequently reordered. I want to be able to press one of the buttons and obtain the index path of that button's table view cell. I've been trying to get this working for days by storing the row of the button in its tag, but when the table gets reordered, the row becomes incorrect and I keep failing at reordering the tags correctly. Any new ideas on how to keep track of the button's cell's index path?
If you feel uncomfortable relying on button.superview, this method should be a little more robust than some of the other answers here:
UIButton *button = (UIButton *)sender;
CGRect buttonFrame = [button convertRect:button.bounds toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonFrame.origin];
This stopped working with iOS 7; check out Mike Weller's answer instead
- (IBAction)clickedButton:(id)sender {
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview;
UITableView *tableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
}
Or shorter:
- (IBAction)clickedButton:(id)sender {
NSIndexPath *indexPath = [(UITableView *)sender.superview.superview indexPathForCell:(UITableViewCell *)sender.superview];
}
Both are untested!
Crawling up view hierarchies with .superview (like all of the existing answers demonstrate) is a really bad way to do things. If UITableViewCell's structure changes (which has happened before) your app will break. Seeing .superview.superview in your code should set off alarm bells.
The button and its handler should be added to a custom UITableViewCell subclass and layed out there. That's where it belongs.
The cell subclass can then delegate out the button event through a standard delegate interface, or a block. You should aim for something like this:
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = ...;
// ...
cell.onButtonTapped = ^{
[self buttonSelectedAtIndexPath:indexPath];
}
// OR
cell.delegate = self;
// ...
}
(Note: if you go the block route, you will need to use a __weak self reference to prevent retain cycles, but I thought that would clutter up the example).
If you take the delegate route you would then have this delegate method to implement:
- (void)cellButtonPressed:(UITableViewCell *)cell
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// ...
}
Your code now has full access to the appropriate context when it handles the event.
Implementing this interface on your cell class should be straightforward.
I don't know why I need to call the method superview twice to get the UITableViewCell.
Update:
Thank for Qiulang, now I got it.
"That's because SDK now has added a private class called UITableViewCellContentView for UITableViewCell, which is button's superview now." – Qiulang
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
UITableView *curTableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [curTableView indexPathForCell:cell];
I had this same issue also and built a simple recursive method that works no matter how many views deep you triggering control is.
-(NSIndexPath*)GetIndexPathFromSender:(id)sender{
if(!sender) { return nil; }
if([sender isKindOfClass:[UITableViewCell class]])
{
UITableViewCell *cell = sender;
return [self.tableView indexPathForCell:cell];
}
return [self GetIndexPathFromSender:((UIView*)[sender superview])];
}
-(void)ButtonClicked:(id)sender{
NSIndexPath *indexPath = [self GetIndexPathFromSender:sender];
}
I have created one Method for getting indexPath, Hope this will help you.
Create Button Action (aMethod:) in cellForRowAtIndexPath
-(void) aMethod:(UIButton *)sender
{
// Calling Magic Method which will return us indexPath.
NSIndexPath *indexPath = [self getButtonIndexPath:sender];
NSLog(#"IndexPath: %li", indexPath.row);
NSLog(#"IndexRow: %li", indexPath.section);
}
// Here is the Magic Method for getting button's indexPath
-(NSIndexPath *) getButtonIndexPath:(UIButton *) button
{
CGRect buttonFrame = [button convertRect:button.bounds toView:groupTable];
return [groupTable indexPathForRowAtPoint:buttonFrame.origin];
}
Use this Perfect working for me.
CGPoint center= [sender center];
CGPoint rootViewPoint = [[sender superview] convertPoint:center toView:_tableView1];
NSIndexPath *indexPath = [_tableView1 indexPathForRowAtPoint:rootViewPoint];
NSLog(#"%#",indexPath);
SWIFT 2 UPDATE
Here's how to find out which button was tapped
#IBAction func yourButton(sender: AnyObject) {
var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(position)
let cell: UITableViewCell = tableView.cellForRowAtIndexPath(indexPath!)! as
UITableViewCell
print(indexPath?.row)
print("Tap tap tap tap")
}