I've got dynamic tableView and one problem. In each tableCell are two buttons.
I'm trying to get indexPath.row on button touched but with no success.
My code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = [self.homeTableView indexPathForSelectedRow];
NSLog(#"%d", indexPath.row);
}
How can I get indexPath.row for touced button (Segue connections are over this two buttons->two connections)?
It's not working because you do not select row when you click button.
With two buttons I would disconnect your segues from buttons and do 2 manual segues in IB then add code like that to handle them:
-(void)button1Pressed:(id)sender {
UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *clickedButtonIndexPath = [self.homeTableView indexPathForCell:clickedCell];
...
[self performSegueWithIdentifier:#"YourManualSegueIdentifier1" sender:self];
}
Edit for second option:
In your MyTableViewCell.h:
#interface MyTableViewCell : UITableViewCell
...
#property (strong, nonatomic) NSIndexPath *cellIndexPath;
...
#end
In your MyTableViewCell.m:
-(void)button1Pressed:(id)sender {
...
NSInteger row = cellIndexPath.row;
...
}
In your MyTableViewController.m:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyTableViewCell *cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// remember index here!
[cell setCellIndexPath:indexPath];
....
return cell;
}
Apple change the UITableViewCell hierarchy in iOS 7
Using iOS 6.1 SDK
<UITableViewCell>
| <UITableViewCellContentView>
| | <UILabel>
Using iOS 7 SDK
<UITableViewCell>
| <UITableViewCellScrollView>
| | <UITableViewCellContentView>
| | | <UILabel>
So if you want to get indexpath at button index then use following code
Using iOS 6 or later SDK
UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *clickedButtonPath = [book_table indexPathForCell:clickedCell];
NSLog(#"index=%#",clickedButtonPath);
Using iOS 7 or 7+ SDK
UITableViewCell *clickedCell = (UITableViewCell *)[[[sender superview] superview]superview];
NSIndexPath *clickedButtonPath = [book_table indexPathForCell:clickedCell];
NSLog(#"index=%ld",(long)clickedButtonPath.item);
I am not using storyboard but once i did it in simple viewconroller based project, i think this may help you.
- (IBAction)goToNew:(id)sender
{
UIButton *btn = (UIButton*) sender;
UITableViewCell *cell = (UITableViewCell*) [btn superview];
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
int row = indexPath.row;
}
Maybe the touch happened to the UIButton instead of the UITableView / UITableViewCell.
Check with :
NSLog(#"%#",[sender class]);
Solved over button.tag
In "cellForRowAtIndexPath" I set button.tag = indexPath.row and then in "- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{"
UIButton *btn = (UIButton*) sender;
NSLog(#"%d", btn.tag);
give button tag = indexpath.row+100;
and get..
-(IBAction)ShowListView:(id)sender
{
UIButton *btn = (UIButton *)sender;
int Iindex = btn.tag-100;
NSLog(#"button title is %#",btn.titleLabel.text);
NSLog(#"button id is %d",Iindex);
NSLog(#"array category is....%#",arrayCategory);
Related
I am using SKSTableView control.I have added button on cell.I have facing one issue When i clicked on button then i got wrong row and subrow.
- (IBAction)btnPickListPressed:(id)sender
{
UIButton *btn=sender;
PicklistTableViewCell *cell = (PicklistTableViewCell *)btn.superview.superview;
NSIndexPath *indexPath = [self.tblView indexPathForCell:cell];
NSLog("%#",indexPath.row);
NSLog("%#"indexPath.subRow);
}
First copy below code and open SKSTableView.h
- (NSIndexPath *)correspondingIndexPathForRowAtIndexPath:(NSIndexPath *)indexPath
paste this below to #interface SKSTableView : UITableView in SKSTableView.h
and replace your action method code to this:
UIButton *btn=sender;
PicklistTableViewCell *cell = (PicklistTableViewCell *)btn.superview.superview;
NSIndexPath *indexPath = [self.tblView indexPathForCell:cell];
NSIndexPath *correspondingIndexPath = [self.tblView correspondingIndexPathForRowAtIndexPath:indexPath];
NSLog("%#",correspondingIndexPath.row);
NSLog("%#"correspondingIndexPath.subRow);
This question already has answers here:
indexPathForCell returns nil since ios7
(3 answers)
Closed 9 years ago.
Before asking this question, I searched a lot on Google and Stackoverflow. Tried also some examples, but I can't make the function work.
Since the hierarchy of the tableview is changed since iOS 7, is it kind of hard to find a solution.
I got a standard tableview with a couple items and one button on the screen.
I need to get the indexPath.row number when selecting an item from the tableview and clicking on the button.
This is my code
- (IBAction)buttonGetNumber:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[(UIView *)[button superview] superview]];
NSLog(#"%i", indexPath.row);
}
This keeps returning a '0', no matter which item I select from the tableview.
I also tried this (2):
- (IBAction)buttonGetNumber:(id)sender {
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *) [[button superview] superview];
NSIndexPath *index = [self.tableView indexPathForCell:cell];
NSLog(#"%i", index.row);
}
This also returns a '0'.
I also tried this (3):
- (IBAction)buttonGetNumber:(id)sender {
UIButton *senderButton = (UIButton *)sender;
UITableViewCell *buttonCell = (UITableViewCell *)[[senderButton superview] superview];
UITableView* table = (UITableView *)[buttonCell superview];
NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
NSInteger rowOfTheCell = [pathOfTheCell row];
NSLog(#"%i", rowOfTheCell);
}
And this makes the application crash.
Any clue how I can solve this?
Create an instance variable _lastClickedRow Set it with tableview delegate like below. And when you click the to "Get Row" button use _lastClickedRow.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
_lastClickedRow = indexPath.row;
}
- (IBAction)buttonGetNumber:(id)sender {
NSLog(#"%d" , _lastClickedRow);
}
If for some reason selected cell doesn't work for you (e.g. for a multiple selection case), you could get row from sender's frame:
- (IBAction)buttonGetNumber:(id)sender
{
CGPoint buttonOrigin = sender.frame.origin;
CGPoint pointInTableview = [self.tableView convertPoint:buttonOrigin fromView:sender.superview];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInTableview];
if (indexPath) {
// Do your work
}
}
You simply set the tag of the UIButton same as the indexPath.row using:
yourButton.tag = indexPath.row;
in didSelectRowForIndexPath:.
Then in buttonGetNumber: method, you get the row number using:
int rowNum = [(UIButton*)sender tag];
Here, you have the advantage of not using any third variable.
I want to get index of touched Text Box in tableview cell. The fact that I could do it before IOS 7. In the past I could get the text box index in below. This method also fails to IOS 7. I read tag should use instead of this method. But I also use tag for each different text box. Because Clicking to the text box I am doing different things, for example opening the picker or opening to the selection view. Plase help me, how can I get the row number of each text box When touched to text box.
-(NSInteger)getTextFieldCellRow:(id)element{
UITableViewCell *cell = (UITableViewCell *)[[(UITextField*)element superview] superview];
UITableView *table = (UITableView *)[cell superview];
NSIndexPath *textFieldIndexPath = [table indexPathForCell:cell];
return textFieldIndexPath.row;
}
Ok, I solved
-(NSIndexPath *) getButtonCellRow:(UITextField *) b {
UITableView *tv = nil;
UIView *superViewTemp = [b superview];
UITableViewCell *cell=nil;
BOOL isFoundTable=FALSE;
BOOL isFoundCell=FALSE;
while(superViewTemp != nil && ![superViewTemp isKindOfClass:[UIWindow class]]){
if ([superViewTemp isKindOfClass:[UITableViewCell class]]) {
cell=(UITableViewCell*)superViewTemp;
isFoundCell = TRUE;
}else if ([superViewTemp isKindOfClass:[UITableView class]]){
tv = (UITableView*)superViewTemp;
isFoundTable = TRUE;
}
superViewTemp = [superViewTemp superview];
if(isFoundCell && isFoundTable){
break;
}
}
if(tv != nil && cell != nil){
return [tv indexPathForCell:(UITableViewCell*)cell];
}
return nil;
}
this should be a very simple solution
UIView *view = textField;
while (![view isKindOfClass:[UITableViewCell class]])
{
view = [view superview];
}
CellClass *cell = (CellClass *)view;
Try with following code:
UIView *contentView = (UIVIew *)[textfield superview];
UITableViewCell *cell = (UITableViewCell *)[contentView superview];
NSIndexPath *indexPath = [self.tableview indexPathForCell:cell];
NSLog(#"%d", indexPath.row);
But in iOS 7, you can get UITableViewCell by following code:
UITableViewCell *cell = (UITableViewCell *)[[contentView superview] superview];
I am using a tableView which loads a custom UITableViewCell with a "Tap" button inside it. A method is called when user clicks the button.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{...
[btnRowTap addTarget:self action:#selector(didButtonTouchUpInside:) forControlEvents:UIControlEventTouchDown];
...
return cell;
}
In the didButtonTouchUpInside method, Im trying to retrieve the value of row selected in the following way:
-(IBAction)didButtonTouchUpInside:(id)sender{
UIButton *btn = (UIButton *) sender;
UITableViewCell *cell = (UITableViewCell *)btn.superview;
NSIndexPath *indexPath = [matchingCustTable indexPathForCell:cell];
NSLog(#"%d",indexPath.row);
}
The problem is that on clicking button at any row, I am getting the same value of 0 every time.
Where am I going wrong?
You must NOT rely on the view hierarchy of a UITableViewCell. This approach will fail in iOS7, because iOS7 changes the view hierarchy of the cell. There will be an additional view between your button and the UITableViewCell.
There are better ways to handle this.
Convert the button frame so it is relative to the tableview
ask the tableView for the indexPath at the origin of the new frame
.
-(IBAction)didButtonTouchUpInside:(id)sender{
UIButton *btn = (UIButton *) sender;
CGRect buttonFrameInTableView = [btn convertRect:btn.bounds toView:matchingCustTable];
NSIndexPath *indexPath = [matchingCustTable indexPathForRowAtPoint:buttonFrameInTableView.origin];
NSLog(#"%d",indexPath.row);
}
set Button tag in to cellForRowAtIndexPath method Befor setting Method like
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{...
btnRowTap.tag=indexPath.row
[btnRowTap addTarget:self action:#selector(didButtonTouchUpInside:) forControlEvents:UIControlEventTouchDown];
...
return cell;
}
and your tapped cell getting like this:-
-(IBAction)didButtonTouchUpInside:(id)sender{
{
UIButton *button = (UIButton*)sender;
NSIndexPath *indPath = [NSIndexPath indexPathForRow:button.tag inSection:0];
//Type cast it to CustomCell
UITableViewCell *cell = (UITableViewCell*)[tblView1 cellForRowAtIndexPath:indPath];
NSLog(#"%d",indPath.row);
}
try like this,if you are adding button to cell content view then use below code.
UITableViewCell *buttonCell = (UITableViewCell *)sender.superview.superview;
UITableView* table1 = (UITableView *)[buttonCell superview];
NSIndexPath* pathOfTheCell = [table1 indexPathForCell:buttonCell];
int rowOfTheCell = [pathOfTheCell row];
int sectionOfTheCell = [pathOfTheCell section];
btn.superview is contentView of UITableviewCell. Use btn.superview.superview instead.
if you already knew the value inside the cell, then
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *currentCell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if ([currentCell.textLabel.text isEqualToString:#"Your Cell Text value" ]){
//Do theStuff here
}
}
here is the code for your ibAction.you dont need to set any tag or anything else
-(IBAction)didButtonTouchUpInside:(id)sender{
NSIndexPath *indexPath =
[tbl
indexPathForCell:(UITableViewCell *)[[sender superview] superview]];
}
I have a custom cell that have a check box,
all is working fine, the checkboxes get check according to a dictionary that I pass to my subclassed UITableViewCell,
but now I need to pass to the class that have the table view the exact cell that my check box was modified so I can set my mutable dictionary with the new checked or unchecked state for that particular cell,
So how to do this?, shall I use a delegate?, this is fine, but the question is, how do I know what cell was my check box modified at?
You can use a delegate like this...
MyCell.h
#protocol MyCellDelegate <NSObject>
-(void)cellCheckBoxWasChanged:(MyCell *)cell;
#end
#interface MyCell : NSObject
#property (nonatomic, weak) id <MyCellDelegate> delegate;
#end
MyCell.m
#implementation MyCell
- (void)checkBoxChanged
{
[self.delegate cellCheckBoxWasChanged:self];
}
#end
Then to find the index you can do...
TableViewController.m
- (void)cellCheckBoxWasChanged:(MyCell *)cell
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// do something to your array.
}
Why don't you pass the UITableViewCell also in the delegate method as self.
So with that cell, you could get the indexpath by
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
set the tag Value of each Checkboxes depending on the cells Indexpath in the cellForRowAtIndexPath: method.
UIButton *checkboxes = customCell.checkButton
[checkboxes setTag:indexPath.row];
then in buttons action method.
check the senders.Tag value to get the exact row of the button pressed
UITableViewCell *cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:sender.tag inSection:0]];
you can do this -
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
if([[[Usercontacts objectAtIndex:indexPath.row]objectForKey:#"isChecked"]isEqualToString:#"NO"])
{
[checkUncheckBtn setImage:[UIImage imageNamed:#"unchecked box.png" ]forState:UIControlStateNormal];
checkUncheckBtn.tag=1;
}
else
{
[checkUncheckBtn setImage:[UIImage imageNamed:#"checked box.png" ]forState:UIControlStateNormal];
checkUncheckBtn.tag=2;
}
[checkUncheckBtn addTarget:self action:#selector(checkUncheckBtnPressed:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
and when you perform checkUncheckBtnPressed: method it looks like
-(void)checkUncheckBtnPressed:(id)sender
{
UIButton *btn=(UIButton*)sender;
UITableViewCell *cell =(UITableViewCell *) [sender superview] ;
NSIndexPath *_indxpath = [createGroupContactsTableView indexPathForCell:cell];
if(btn.tag==1)
{
[btn setImage:[UIImage imageNamed:#"checked box.png" ]forState:UIControlStateNormal];
btn.tag=2;
[[Usercontacts objectAtIndex:_indxpath.row]setObject:#"YES" forKey:#"isChecked"];
}
else
{
[btn setImage:[UIImage imageNamed:#"unchecked box.png" ]forState:UIControlStateNormal];
btn.tag=1;
[[Usercontacts objectAtIndex:_indxpath.row]setObject:#"NO" forKey:#"isChecked"];
}
}
Here's an alternative to having the Cells listen to events from the checkBoxes and forward them to the UITableViewController using the delegate pattern:
Have the UITableViewController listen to events from the checkBoxes and use the following code to determine the NSIndexPath of the cell:
#implementation UITableView (MyCategory)
-(NSIndexPath*)indexPathOfCellComponent:(UIView*)component {
if([component isDescendantOfView:self] && component != self) {
CGPoint point = [component.superview convertPoint:component.center toView:self];
return [self indexPathForRowAtPoint:point];
}
else {
return nil;
}
}
#end