Custom Cell button Click - ios

My scenario is as follow's:
Custom Cell View
1) I am populating data from server in the custom cell view which is perfectly populated, i want a link store in my array which i want to open in browser, so i want to check which index.row button is clicked so that against that row i can get the url link and open it in browser, so far i have found the solution of button tags but that doesn't work's as well, as if we have two cell's in the screen at same time on click of button both button return's same tag.
2) As the image attached i have another storyboard in which i want to segue to a new view controller, same as mentioned above, i want to pass a specific post title and key as well.
I hope every thing is clear.
Thank's in advance.

To answer the first part of your question. Tags are a pain. It's better to pass along the UIButton as the sender, and, in the action for the button, then you can say something like:
-(void) buttonPresse:(UIButton *)sender
{
CGPoint location = [self.tableView convertPoint:sender.bounds.origin fromView:sender];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *cell = [self.table cellForRowAtIndexPath];
//Do what you want with the cell or indexPath
}

I have found the solution of button tags but that doesn't work's as well
Perform following steps to detect which button is selected.
Type the code snippet given below in cellForRowAtIndexPath: method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// DEFINE CELL
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// SET ACTION METHOD ON CALL BUTTON
UIButton *button = (UIButton *) [self.view viewWithTag:40];
[button setUserInteractionEnabled:YES];
[button addTarget:self action:#selector(checkButtonTapped:) forControlEvents:UIControlEventAllTouchEvents];
}
Add following method for checkButtonTapped:.
- (void)checkButtonTapped:(UIButton *)sender
{
// GET POINT OF THE BUTTON PRESSED
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
// GET INDEXPATH FOR THE CELL WHERE THE BUTTON IS PRESSED
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
//Use indxPath.row to get item
//Perform operations
}
}
There is another approach if you want to perform action according to the cell selected by the user.
For the case where you want to check which row of the cell is clicked you should use following method.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"ShowindexPath%ld", (long)indexPath.row); }
Here we check for the user interaction on cell. indexPath.row will return index number for the cell selected by user. You can perform other actions in place of NSLog method.
For the purpose to send value while performing segue use following steps:
Create property in the NewViewController.h file where you want to perform segue as follow:
#property (nonatomic) NSString* receivedValue;
#synthesize property by writing following code in NewViewController.m file within #implementation and #end
#synthesize receivedValue;
ImportNewViewController.h file in TableViewController.m file.
Go to prepareForSegue: method in the TableViewController.m file from where you want to send the value and write following code according to your class names within it.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NewViewController *nVC = [segue destinationViewController];
[nVC setReceivedValue:sendValue];
}
Here sendValue is the value that you want to send.
That's all.
Build and run your project and enjoy.

You can extend UITableViewCell and add a touple property to it. key containing the index.row and value containing the URL eg:- 1:"www.stackoverflow.com". When you click on a button, all you have to figure out is the index.row and from that you can get the value that you are looking for.

you can add target for button in cellForRowAtIndexPath like :
[cell.yourButton addTarget:self action:#selector(buttonAction:event:) forControlEvents:UIControlEventTouchUpInside];
here you can receive the action for this button
-(void)buttonAction:(UIButton *)sender event:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPos = [touch locationInView:self.tblview];
NSIndexPath *indexPath = [self.tblview indexPathForRowAtPoint:touchPos];
if(indexPath != nil){
// handle click event..
}
}
surely it will work.........

Related

UIButton tag value doesn't pass in prepareForSegue method in UITableViewController

The feed of my app is managed by a UITableViewController where I set custom cells that are instances of a UITableViewCell sub class.
One property of that sub class is a UIButton called flameRelation:
#property (weak) IBOutlet UIButton* flameRelation;
I am creating a dynamic segue to a detail view controller depending on the class of the sender. If the sender is the cell itself, I pass a given set of data to my detail view controller. If the sender is the flameRelation button, I pass another.
To achieve this, I am looking at the following 2-step approach:
1) Since I need to know the indexpath.row of the cell where the FlameRelation button was pressed, I set the tag of that button in the UITableView method that sets each cell of my feed as follows:
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Set a bunch of things before setting UIButton flameRelation tag
[cell.flameRelation setTag:indexPath.row];
And I am printing the tag which allows me to check that the tag is being set when I scroll down my feed after launching my build (I see the numbers incrementing as I scroll down, as expected).
NSLog(#"The button tag for this cell is set to %ld",(long)[cell.flameRelation tag]);
2) In the prepareForSegue method that allows the user to transition to the detail view controller with the relevant information, I test the class of the sender first. If the class of the sender is UIButton, I attempt to pass the right information to the detail view controller by setting the value of the indexpath to the value of the tag:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"FlameDetail"]) {
FlameDetailViewController* flameDetailController = (FlameDetailViewController*) segue.destinationViewController;
if ([sender isKindOfClass:[FlameCellTableViewCell class]])
{
NSIndexPath* indexPath = [self.tableView indexPathForCell:sender];
NSLog(#"The indexPath is: %#", indexPath);
flameDetailController.flame = [self.feed flameAtIndex:indexPath.row];
NSLog(#"class for object sender: %#", NSStringFromClass([sender class]));
}
else if ([sender isKindOfClass:[UIButton class]])
{
NSLog(#"The button tag is set to %ld",(long)[sender tag]);
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:[sender tag] inSection:0];
NSLog(#"The indexPath from UIButton is: %#", indexPath);
flameDetailController.flame = [self.feed flameAtIndex:indexPath.row];
NSLog(#"The value of indexPath.row is %ld",(long)indexPath.row);
NSLog(#"class for object sender: %#", NSStringFromClass([sender class]));
flameDetailController.findOutView.hidden = NO;
[flameDetailController.flameAction setTitle:#"CHAT NOW" forState:UIControlStateNormal];
NSLog(#"Yes, the sender is UIButton");
NSLog(#"The title of flameAction is set to %#", flameDetailController.flameAction.titleLabel.text);
}
}
Everything works well if I tap on the cell itself, but if I tap on the flameRelation button, I see in my logs that the getter on tag returns 0. Which obviously doesn't transfer the proper information to my target view controller.
Thanks!
First of all why you are converting your tag value to indexPath and then getting your model data with the row number?
Your code:
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:[sender tag] inSection:0];
flameDetailController.flame = [self.feed flameAtIndex:indexPath.row];
Try this instead:
flameDetailController.flame = [self.feed flameAtIndex:sender.tag];
I do not see a reason why this approach would not work. If it does not you need to share more code/details.
However, I would want to suggest another alternate (no so great though):
UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *clickedButtonPath = [self.tableView indexPathForCell:clickedCell];

iOS >> UITableViewCell >> Custom Cell >> Row Number

Does a UITableViewCell (or a subclass of) has a way to recognise 'on the run' in which Row it is currently at? - not via the didSelectRowAtIndexPath method...
If I subclass UITableViewCell and have some control objects in it (button, text field, etc...), and I wish to respond to that control usage, I wish to respond in consideration to the cell current row; doing so in MYTableViewCell.m file.
What I have done so far, is assign the tag Property with the Row number at creation time (cellForRowAtIndexPath); and then I can create my own Protocol in the MYTableViewCell file, create a 'delegate' Property and assign each cell to the VC as its delegate and send it messages. But that seems like a lot to do for something so basic.
Is there a 'built in' way to do that?
Or a simpler way...
Check out the
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell
method. I tend to add a tableView property to the cell and set it when creating the cell to the tableView that will own that cell. Then call:
[tableView indexPathForCell:cell]
Which returns the indexPath for that cell, giving you the section and row. This is better than using a tag of course, since it includes the section, and is always valid, even if the cell changes position (others inserted or deleted above it, or it actually moves).
Well you can use the cellatrowforindexpath method to perform such action.
for example if you want to perform some action on button click, you can do like that.
cell.buttonName.tag=indexPath.row;
and in the action that you have attached to that button do like that.
(ibaction)performsomeAction:(id)sender{
UIButton *btn=(UIButton*)sender;
nslog(#"the row on which i have clicked is %d",btn.tag);
}
this will tell you which row you are currently.
There are different ways to obtain the index path of a cell after touching a control inside it, without using the tag property or coupling the cell with its table view.
The first thing to do is to add the target-action to your button, like this:
[button addTarget:cell action:#selector(buttonTapped:withEvent:) forControlEvents:UIControlEventTouchUpInside];
Then you can use the event parameter of the action method:
- (void)buttonTapped:(id)sender withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
// ....
}
Or the view hierarchy to retrieve the cell:
- (void)buttonTapped:(id)sender withEvent:(UIEvent *)event
{
UITableViewCell *cell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// ....
}
Or the position of the sender (i.e. the control):
- (void)buttonTapped:(id)sender withEvent:(UIEvent *)event
{
CGPoint position = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:position];
// ....
}

How to determine a Button click in a Custom UITableViewCell?

i have a TableView with a Custom Cell and a Section Header. The Header shows me the Country and the custom Cell shows me the City.
which look like this:
USA
New York
Los Angeles
Germany
Berlin
Frakfurt
every Cell got a Button. after a press it will navigate and push the city name to the detail view .
The Problem is, that i don't know how to determine the city name after i pressed the button.
I had a solution but it doesn't work anymore:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
StandortCell *cell = (StandortCell *)[tableView dequeueReusableCellWithIdentifier:#"ortCell"];
[cell.detailButton setTag:indexPath.row];
cell.ortLabel.text = [managedObject valueForKey:#"stadtname"];
}
- (IBAction)detailButton:(id)sender {
UIView *contentView = [sender superview];
UITableViewCell *cell = (UITableViewCell *)[contentView superview];
NSIndexPath *cellIndexPath = [self.tableView indexPathForCell:cell];
NSInteger section = cellIndexPath.section;
UIButton * myButton = sender;
int row=myButton.tag;
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:row inSection:section];
StrasseViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"strasse"];
self.selectedStandort = [self.fetchedResultsController objectAtIndexPath:indexPath];
detail.currentStandort = self.selectedStandort;
[self.navigationController pushViewController:detail animated:YES];
}
when i use my old code it will just show the correct street row in the first section. it didn't detect the other sections(Countries);
When i choose the first city in the thirt section. it will display me the first city in the first section.
I hope you can help me.
use this I hope it will solve your purpose.
Create a button pressed method in your view controller
(IBAction)detailButton:(UIButton *)sender {
CustomUITableViewCellName *cell = (CustomUITableViewCellName *)[[sender superview]superview];
NSIndexPath *cellIndexPath = [YOUR_TABLE_NAME indexPathForCell:cell];
}
For ios 7 add another superview.
Now in this way you will get your IndexPath and you an get the current row by using
indexPath.row or indexPath.section.
You can get the title using sender.title property.
You can use this indexPath in your array to the required details.
You need to send row and section information seperately so make tag as
Tag= row*1000+section.
now from tag get section and row value using row= tag/1000
section =tag%1000
use this value to make correct index path or find some better then 2 mins solution to get that.
Caution its a workaround correct will be to
Subclass UIButton
Add a indexpath property int it
make your class to make button object and insted of tag set indexpath property.
in CustomButton.h
#interface CustomButton :UIButton
#property (nonatomic,assign)NSIndexPath *path;
#end
in CustomButton.m
#implementation CustomButton
#synthesize path;
#end
Use this custom button on your table view cell and instead of tag set path property

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

I have a UITableView in my application where I have custom UITableViewCell which contains a UITextField. What I would like to do is get the correct index of the row when I select a particular textfield from that row. Unfortunately, I am only able to get the correct index of the row if I actually click on the row, and not when I select the textfield itself. I am implementing the <UITextFieldDelegate>, and when I select a particular UITextField, I call the method:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
int rowTest = [_table indexPathForSelectedRow].row;
int rowTest1 = [_cell.tireCodeField tag];
NSLog(#"the current row is: %d", rowTest1);
NSLog(#"and this row is: %d", rowTest);
return YES;
}
The problem is that the value for the row that I am getting is from whenever the method:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
...
}
get's called. It is as if there is a disconnect between the UITextField and the row in the table it resides in. Is there a way for me to select a particular textField, and get the
Is there a way for me to get the index of the row by selecting the UITextField that resides within it, instead of selecting the row itself?
Thanks in advance to all who reply.
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).
Well, assuming that the cell is the direct superview or the text field, you can directly ask for the text field's superview, cast to UITableViewCell, and then ask your instance of UITableView for the index path of that cell. Here's an example:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
UITableViewCell *cell = (UITableViewCell *)textField.superview; // cell-->textfield
//UITableViewCell *cell = (UITableViewCell *)textField.superview.superview; // cell-->contentView-->textfield
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
return YES;
}
If you're looking for a more dynamic solution that works across multiple versions of iOS, then you'll probably want to use the following quoted from #Marko Nikolovski here
// Get the cell in which the textfield is embedded
id textFieldSuper = textField;
while (![textFieldSuper isKindOfClass:[UITableViewCell class]]) {
textFieldSuper = [textFieldSuper superview];
}
// Get that cell's index path
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)textFieldSuper];
This method crawls up the superview until it encounters a UITableViewCell. This keeps the code working even when the cell's view hierarchy changes, like it did from iOS 6 to 7.
I thought I'd post this slightly (!) late answer as I was trying to do this for ages and then remember another method (which if I say so myself is one of the best ways) of getting the index path for a cell when a UIButton was tapped.
In a similar way you can get the CGPoint of the cell.
-(NSIndexPath *)indexPathForTextField:(UITextField *)textField
{
CGPoint point = [textField convertPoint:CGPointZero toView:self.tableView];
return [self.tableView indexPathForRowAtPoint:point];
}
-(void)textDidChangeForTextFieldInCell:(UITextField *)textField
{
NSIndexPath *indexPath = [self indexPathForTextField:textField];
// Now you can update the object at indexPath for your model!
}
I think this is far neater than relying on tags or the even yuckier method of looking at superviews!
As it seems you are working with tags,using the UITextFieldDelegate,you can declare this methods in order to select the row.
-(void)textFieldDidBeginEditing:(UITextField *)textField{
int rowTest1 = textField.tag;
[myTableview selectRowAtIndexPath:[NSIndexPath indexPathForRow:rowTest1 inSection:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
}
-(void)textFieldDidEndEditing:(UITextField *)textField{
[textField resignFirstResponder];
}
UITableViewCell *textFieldCell = (UITableViewCell*) [[[textfield superview]superview]superview];
NSIndexPath *indexPath = [self.editProfileTableView indexPathForCell:textFieldCell];

Custom UITableViewCell and IBAction

I have a custom UITableViewCell on which I have added a button, I have associated that button on an IBAction in my viewController. Now the problem that i am facing is how do I know from which cell that button was created. When I present my viewController which has a table in it and has multiple rows (custom UITableViewCell), now when the user presses the button the action is getting called, but how do I know which row was it.
Because based on the row index I need to store some value.
Edit: I have some clue on it now, but still I am not sure how will I do it, so it seems like on my tableViewController cellForRowAtIndexPath method I have to do something like this
[cell.button1 addTarget:self action:#selector(addToCart:) forControlEvents:UIControlEventTouchUpInside];
And then I have to write a method
-(IBAction) addToCart:(id) sender
But still what I don't know is how do i get the row index in my addToCart method.
Appreciate your help.
Ok, finally I got the answer, looking into different forums, people were suggesting to do something like this
in the custom table view controller in cellForRowAtIndexPath do this
cell.addToCart.tag = indexPath.row;
[cell.addToCart addTarget:self action:#selector(addToCart:)
forControlEvents:UIControlEventTouchUpInside];
where addToCart is name of UIButton in my customUITableViewCell. It didn't seems to work for me. So this is what I did
-(IBAction) addToCart:(id) sender{
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)
[[sender superview] superview]];
NSLog(#"The row id is %d", indexPath.row);
}
And then through interfacebuilder I associated the action of my button to addToCart IBAction on my table view controller.
Much less hackerific.
[cell.button1 addTarget:self action:#selector(addToCart:event:) forControlEvents:UIControlEventTouchUpInside];
- (void)addToCart:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
}
The accepted answer does not work any more. Please refer to this post
It does it that way:
- (void)checkButtonTapped:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
...
}
}
Many of the developer used custom view to show custom cell on Table view for older version of iOS. If you are one of them, then you will have to face a problem that your button click action will no longer work with iOS7.
How to resolve this:
You have two options:
Option 1: Create the new lay out with new table cell instead of taking view. and put all layouts again in table cell.
I know, this will require a lot of effort.If you don't want to do this, we have a very small hack for it:option 2
Option 2: Create a IBOutlet for your button and add this button as a subview of your cell's content view.
[self.myCell.contentView addSubview:self.btn_click];
The above line of code will add btn_click as a subview of you content view. Now button click action should work.

Resources