UIButton placed on top of tableviewcell - iphone

I have UIButton which is placed on top of each UITableviewCell . It is custom tableview . When i click on tableviewcell it goes into another tableview where (Tableview) contains the data in each cell .
This is the way i get the details of the 2nd tableview ....customCellData is the db query method which gives out the cell number ..(Ex if i click 2nd cell of first tableview customcell returns the value )
(bookArray - contains the list of items present in 2nd cell of first tableviewcell)
The following code is didSelectForRowAtIndexPath
NSDictionary *selectedAuthor = nil;
NSArray *sectionArray=[mainIndexDictionary objectForKey:[allKeysArray objectAtIndex:indexPath.section]];
selectedAuthor = [sectionArray objectAtIndex:indexPath.row];
iPath=[[selectedAuthor objectForKey:#"SymptIndexID"] intValue];
NSLog(#"iPath - %d",iPath);
authortitleString=[[selectedAuthor objectForKey:#"authorIndexName"]stringByAppendingString:#" cure!"];
}
bookArray=[objDB customCellData:(NSInteger)iPath];
[self.view bringSubviewToFront:authorView];
[bookTableView scrollRectToVisible:CGRectMake(0.0, 0.0, 320.0,10.0) animated:NO];
[bookTableView reloadData]
Now i want to program in such a way where .when i click on the UIButton which is there in 1st tableview it should contain the data of the 2nd tableview . I cant access indexPath since i will be doing this in seperate method ( In didselectrowatindexpath if i give indexpath for that particular cell the indexpath is found )
Will anyone please help me .
Updated Code
in cellForRowAtIndexPath
cell.shareFacebookButton.tag = indexPath.row;
[cell.shareFacebookButton addTarget:self action:#selector(facebookShare:) forControlEvents:UIControlEventTouchUpInside];
return cell;
-(IBAction)facebookShare:(id)sender
{
UIButton *button = (UIButton *)sender;
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
UITableView *tableView = (UITableView *)cell.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
NSInteger indexPathNumber = indexPath.row;
NSLog(#"IndexPath is -- > %d" , indexPathNumber);
}

Answer Updated
Ok, Below is the function you need to use for custom cell buttons
"cellForRowAtIndexPath" or use any other given appropriate function.
And to identify which button was clicked, do as below
<buttonid>.tag = <indexPath>.row;
Regards,
Ravi

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 UITableview cell.textlabel.text value from button click?

i am a newbie to iphone development.
I am working on a project where i am having a UItableview , i placed a button in each row .
Now my UItableView have a cell.textlabel, detailLabel, and a button placed programatically.
In cell.textlabel i have some values from json(each label have different values) and just at the right corner of each row , i placed a button.
Now i want the cell.textlable.text value of that row only whose button is pressed.
I am getting the same value for each button.
So , my question is , how to get labeltext value of the specific row whose button is pressed ?
attach a tag with your button during its creation e.g. button1.tag = 9999;
in your button click action grab the button as sender
-(void)buttonaction:(UIButton*)sender
{
UITableViewCell * selectedCell = nil;
for(UITableViewCell *cell in [tableView visibleCells])
{
if([cell viewWithTag:9999] == sender)
{
selectedCell = cell;
break;
}
}
//do whatever you like with selected cell now.
}
I hope it helps!!!
Solved like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
UIButton *tableCellButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect]retain];
tableCellButton.frame = CGRectMake(200, 1, 80, 20);
[tableCellButton setTitle:#"showing" forState:UIControlStateNormal];
[tableCellButton addTarget:self action:#selector(shortcutBottonClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:tableCellButton];
} NSDictionary *listing = [ self.temp objectAtIndex:indexPath.row];
cell.textLabel.text = [listing objectForKey:#"0"];
return cell;
}
-(IBAction) shortcutBottonClicked:(id)sender{
//this code solved the problem
indexPath = [self.tableView indexPathForCell:(UITableViewCell*)[sender superview]];
mlsid2 = [self.tableView cellForRowAtIndexPath:indexPath].textLabel.text;
}
I think you mean that each row in the table has a button, and any number of them can be pressed. After the user is done pressing buttons for rows, you need to get which rows of data have been pressed.
If I read you correclty then unless your table is static, it will work something like the following:
You need to have a datastructure like the one I'm assuming you have for your UITableview datasource. For example, an NSArray full of NSNumber objects, one corresponding to each row of data. When the button in a row is pressed, the corresponding NSNumber is set 1. When you need it, just iterate through the NSArray of NSNumbers to know the corresponding rows in your table's datasource that had it's button pressed.
One thing to be aware of is that UItableview cells that you see in the UI are normally reused as the user scrolls - at least this is the case if you have a variable amount of data and rows for your table (as opposed to static), so you can't rely on the UI elements, like the button, for remembering the state
in first view .h file
#
class viewController;
#import <UIKit/UIKit.h>
#interface firstViewController : UITableViewController<UITableViewDelegate, UITableViewDataSource> {
NSString *_cellTitle;
}
#end
first view .m file in didSelectRowAtIndex method add this code like
viewController *detailViewController = [[viewController alloc] initWithNibName:#"viewController" bundle:nil];
NSInteger row = [indexPath row];
_rowTitle = [_detailList objectAtIndex:row];
detailViewController._barTitle = _rowTitle ;
or you can do this in buttonPressed method
then in the second view .h section -
#interface viewController : UIViewController {
NSString *_barTitle;
}
#property (nonatomic, retain) NSString *_barTitle;
#end
synthesize this property in implementation section
in .m and under viewDidLoad method
self.navigationItem.title = _barTitle;
don't forget to import second view .h file
hope this helps

Custom UITableViewCell button action?

I've been looking around to find a solution to this, but can't seem to find one that works for me. I have a custom cell with a button inside. My problem is how do I pass the indexPath to the action method?
Right now I'm doing
[cell.showRewards addTarget:self action:#selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
In my cellForRowAtIndexPath method and my method is:
-(IBAction)myAction:(id)sender{
NSIndexPath *indexPath = [self.tableView indexPathForCell:(MyCustomCell *)[sender superview]];
NSLog(#"Selected row is: %d",indexPath.row);
}
Any tips? Thanks.
cell.showRewards.tag = indexPath.row;
-(IBAction)myAction:(id)sender
{
UIButton *btn = (UIButton *)sender;
int indexrow = btn.tag;
NSLog(#"Selected row is: %d",indexrow);
}
Just want to add what I believe is the best solution of all: a category on UIView.
It's as simple as this:
- (void)somethingHappened:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender parentCell]];
// Your code here...
}
Just use this category on UIView:
#interface UIView (ParentCell)
- (UITableViewCell *)parentCell;
#end
#implementation UIView (ParentCell)
- (UITableViewCell *)parentCell
{
UIView *superview = self.superview;
while( superview != nil ) {
if( [superview isKindOfClass:[UITableViewCell class]] )
return (UITableViewCell *)superview;
superview = superview.superview;
}
return nil;
}
#end
While I feel setting tag for the button is one way to go. You might need to write code to make sure each time the cell gets reused, the appropriate tag gets updated on the button object.
Instead I have a feeling this could work. Try this -
-(IBAction)myAction:(id)sender
{
CGPoint location = [sender locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
UITableViewCell *swipeCell = [self.tableView cellForRowAtIndexPath:indexPath];
NSLog(#"Selected row: %d", indexPath.row);
//......
}
Essentially what you are doing is getting the coordinates of where the click happened with respect to your tableView. After getting the coordinates, tableView can give you the indexPath by using the method indexPathForRowAtPoint:. You are good to go after this...
Voila, you have not just the indexPath but also the actual cell where the click happened. To get the actual data from your datasource (assuming its NSArray), you can do -
[datasource objectAtIndex:[indexPath row]];
Try this one.
cell.showRewards.tag=indextPath.row
implement this in cellforrowatindexpath tableview's method.
-(IBAction)myAction:(id)sender{
UIButton* btn=(UIButton*)sender;
NSLog(#"Selected row is: %d",btn.tag);
}
You set the button tag value = indexpath and check it in function if tag value is this do what u want
In custom UITableViewCell class:
[self.contentView addSubview:but_you];
In cellForRowAtIndexPath method you can write:
[cell.showRewards addTarget:self action:#selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
cell.showRewards.tag = indexPath.row;
You can assign indexpath to button tag and access in your method like
cell.showRewards.tag = indexPath.row;
-(IBAction)myAction:(id)sender
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:[sender tag]];
NSLog(#"Selected row is: %d",indexPath.row);
}
I find it incredible that there isn't really a decent solution to this.
For whatever reason, I find the tagging methods and the 'using the visual location of the cell on the screen to identify the correct model object' outlined in the other answers a bit dirty.
Here are two different approaches to the problem:
Subclassing UITableViewCell
The solution I went with was to sub class UITableViewCell
#interface MyCustomCell : UITableViewCell
#property (nonatomic, strong) Model *myModelObject;
#end
When creating the cell in cellForRowAtIndexPath: you are likely to be using the model object to populate the cell data. In this method you can assign the model object to the cell.
And then in the button tap handler:
MatchTile *cell = (MatchTile *) sender.superview.superview;
if (cell && cell.myModelObject)
{
//Use cell.myModelObject
}
I'm not 100% happy with this solution to be honest. Attaching domain object to such a specialised UIKit component feels like bad practice.
Use Objective-C Associative Objects
If you don't want to subclass the cell there is a another bit of trickery you can use to associate the model object with the cell and retrieve it later.
To retrieve the model object from the cell, you will need a unique key to identify it. Define one like this:
static char* OBJECT_KEY = "uniqueRetrievalKey";
Add the following line to your cellForRowAtIndexPath: method when you are using the model object to populate the cell. This will associate your model object with the cell object.
objc_setAssociatedObject(cell, OBJECT_KEY, myModelObject, OBJC_ASSOCIATION_RETAIN);
And then anywhere you have a reference to that cell you can retrieve the model object using:
MyModelObject *myModelObject = (MyModelObject *) objc_getAssociatedObject(cell, OBJECT_KEY);
In reflection, although I opted for the first (because I'd already subclassed the cell), the second solution is probably a bit cleaner since it remains the responsibility of the ViewController to attach and retrieve the model object. The UITableViewCell doesn't need to know anything about it.
In [sender superview] you access not MyCustomCell, but it's contentView.
Read UITableViewCell Class Reference:
contentView
Returns the content view of the cell object. (read-only)
#property(nonatomic, readonly, retain) UIView *contentView
Discussion:
The content view of a UITableViewCell object is the default superview for content displayed by the cell. If you want to customize cells by simply adding additional views, you should add them to the content view so they will be positioned appropriately as the cell transitions into and out of editing mode.
Easiest way to modify your code is to use [[sender superview] superview].
But this will stop working if you later modify your cell and insert button in another view.
contentView appeared in iPhoneOS 2.0. Similar future modification will influence your code. That the reason why I don't suggest to use this way.
In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method write the code below:
[cell.zoomButton addTarget:self action:#selector(navigateAction:) forControlEvents:UIControlEventTouchUpInside];
cell.zoomButton.tag=indexPath.row;
Then write a method like this:
-(IBAction)navigateAction:(id)sender
{
UIButton *btn = (UIButton *)sender;
int indexrow = btn.tag;
NSLog(#"Selected row is: %d",indexrow);
currentBook = [[bookListParser bookListArray] objectAtIndex:indexrow];
KitapDetayViewController *kitapDetayViewController;
if(IS_IPHONE_5)
{
kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:#"KitapDetayViewController" bundle:Nil];
}
else
{
kitapDetayViewController = [[KitapDetayViewController alloc] initWithNibName:#"KitapDetayViewController_iPhone4" bundle:Nil];
}
kitapDetayViewController.detailImageUrl = currentBook.detailImageUrl;
kitapDetayViewController.bookAuthor = currentBook.bookAuthor;
kitapDetayViewController.bookName = currentBook.bookName;
kitapDetayViewController.bookDescription = currentBook.bookDescription;
kitapDetayViewController.bookNarrator=currentBook.bookNarrator;
kitapDetayViewController.bookOrderHistory=currentBook.bookOrderDate;
int byte=[currentBook.bookSizeAtByte intValue];
int mb=byte/(1024*1024);
NSString *mbString = [NSString stringWithFormat:#"%d", mb];
kitapDetayViewController.bookSize=mbString;
kitapDetayViewController.bookOrderPrice=currentBook.priceAsText;
kitapDetayViewController.bookDuration=currentBook.bookDuration;
kitapDetayViewController.chapterNameListArray=self.chapterNameListArray;
// [[bookListParser bookListArray ]release];
[self.navigationController pushViewController:kitapDetayViewController animated:YES];
}
If you want the indexPath of the button Detecting which UIButton was pressed in a UITableView describe how to.
basically the button action becomes:
- (void)checkButtonTapped:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
...
}
}
Here is the "Simplest Way" to do it (Tested on IOS11):
NSIndexPath *indexPath = [myTable indexPathForRowAtPoint:[[[sender superview] superview] center]];

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.