I have searched all over the web and cant seem to find a solution to this simple problem. I have a table view of buttons when the work "like". When the Button is pressed, it changes the word to "Unlike". I got it to work but when I scroll down the table, I see other buttosn also change to "unlike" and sometimes overlaps it with "Like". And when I scroll back up, the original button I selected changes back to normal state. I understand the cells are reusable and thats why I am using a mutable array for my data source and still it doesnt work. Please help!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton setTitle:#"Like" forState:UIControlStateNormal];
myButton addTarget:self action:#selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
myButton.frame = CGRectMake(14.0, 10.0, 125.0, 25.0);
myButton.tag =indexPath.row;
[cell.contentView addSubview:myButton];
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
return cell;
}
the action method:
-(void)tapped:(id)sender {
UIButton *senderButton = (UIButton *)sender;
UITableViewCell *parentCell = [[sender superview]superview];
NSIndexPath *indexPathLiked = [table indexPathForCell:parentCell];
[array replaceObjectAtIndex:senderButton.tag withObject:[NSNumber numberWithInt:1]];
[sender setTitle:#"Unlike" forState:UIControlStateNormal];
}
If the table calls the cellForRowAtIndexPath you create all the time a new button. When you get a reused cell the button still exists and you put a new one over there.
Change your method to:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton setTitle:#"Like" forState:UIControlStateNormal];
myButton addTarget:self action:#selector(tapped:) forControlEvents:UIControlEventTouchUpInside];
myButton.frame = CGRectMake(14.0, 10.0, 125.0, 25.0);
myButton.tag =indexPath.row;
[cell.contentView addSubview:myButton];
}
else {
// todo: change the button title to "like" or "unliked" value
}
cell.textLabel.text = [recipes objectAtIndex:indexPath.row];
P.S. This make no sense, you doesn't use that, why you do that?
UITableViewCell *parentCell = [[sender superview]superview];
NSIndexPath *indexPathLiked = [table indexPathForCell:parentCell];
If you have only one section you can get the cell without using superview:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0]
UITableViewCell *parentCell = [table cellForRowAtIndexPath:indexPath];
Related
I have two UIButton in a UITableViewCell subclass, and in view controller class i have have its selector method, but on clicking on button it always gives the last tag value assigned inside cellForRowAtIndexPath method.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"cell";
customCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
customCell.oneYear.tag = indexPath.row;
customCell.threeYearButton.tag = indexPath.row + 50;
[customCell.oneYear addTarget:self
action:#selector(oneYearButtonAction)
forControlEvents:UIControlEventTouchUpInside];
[customCell.threeYearButton addTarget:self
action:#selector(threeYearButtonAction)
forControlEvents:UIControlEventTouchUpInside];
[customCell setSelectionStyle:UITableViewCellSelectionStyleNone];
It works fine if i use IBAction, but I have to use selector method, which gives above issue.
Kindly help.
You need to create new instance of your custom class with cellForRowAtIndexPath instead of that you are using the same instance customCell.
Instead of this:
customCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
You need to create new object like this:
CustomCellName *customCell = (CustomCellName*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Edit: Instead of using tag with your cell's button action you can try like this way.
-(void)oneYearButtonAction:(UIButton*)sender {
CGPoint center= sender.center;
CGPoint rootViewPoint = [sender.superview convertPoint:center toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rootViewPoint];
CustomCellName *currentCell = [self.tableView cellForRowAtIndexPath:indexPath];
}
You have declared the cell out of the cellForRow method. If you do this your cell object will contains the last object thats why your button always have last tag.
Solution
Declare your object for cell like this in cellForRow
MyCustomCell *customCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; //what ever your class name be I am says MyCustomCell.
NOTE: If you want to use cell object in any other method then there will be lots of other properties are available.
HOW TO GET CELL OBJECT IN BUTTON ACTION METHOD
- (IBAction)btnShowClicked:(UIButton*)sender {
CGPoint buttonPosition = [sender convertPoint:CGPointZero tblObject];
NSIndexPath *indexPath = [tblObject indexPathForRowAtPoint:buttonPosition];
MyCustomCell *customCell = [tblObject cellForRowAtIndexPath:indexPath];
I know you have already resolved the issue. Still posting for someone who might need complete code. FYI, you can use the same method for both buttons, you can directly check in that method which button was clicked with btn.tag as button object is already passed.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
customTableCell *customCell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
[customCell.btn1 setTitle:[NSString stringWithFormat:#"Button %ld",(long)indexPath.row]
forState:UIControlStateNormal];
[customCell.btn2 setTitle:[NSString stringWithFormat:#"Button %ld",(long)indexPath.row+10]
forState:UIControlStateNormal];
[customCell.btn1 setTag:indexPath.row];
[customCell.btn2 setTag:indexPath.row+10];
[customCell.btn1 addTarget:self action:#selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[customCell.btn2 addTarget:self action:#selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
return customCell;
}
-(void) btnClicked:(UIButton *) btn {
UIAlertController *alertC = [UIAlertController alertControllerWithTitle:#"" message:[NSString stringWithFormat:#"Button %ld tapped",(long)btn.tag] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *action = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleCancel handler:nil];
[alertC addAction:action];
[self presentViewController:alertC animated:true completion:nil];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 5;
}
I have create this redio button in cellForRowAtIndexPath
btnper = [UIButton buttonWithType:UIButtonTypeCustom];
btnper.frame = CGRectMake(10, 10, 50, 30);
btnper.tag = indexPath.row;
btnper.titleLabel.font = [UIFont systemFontOfSize:13.0f];
[btnper setImage:[UIImage imageNamed:#"Radiooff1"]
forState:UIControlStateNormal];
[btnper setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btnper setTitle:#" 0%" forState:UIControlStateNormal];
[btnper addTarget:self action:#selector(btnperPress:)
forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:btnper];
this is my Action Method to identify which cell button is pressed
- (IBAction)btnperPress:(UIButton *)sender {
NSInteger selectedCheckBox = sender.tag;
NSLog (#"%d",selectedCheckBox);
}
I am using simple tableview and i have add button in every cell , The Problem is how to get button text from cell number second and any other cell number get button text i am using this code but its not working
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
UITableViewCell *cell = [tbl_view cellForRowAtIndexPath:indexPath];
for( UITableViewCell *getview in cell.subviews)
{
if([getview isKindOfClass:[UIButton class]])
{
NSLog(#"sdfsdfsd");
// UIButton *button = (UIButton *);
}
}
This code is set button in tableview cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
UILabel *fromLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 5, 250,20)];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
cell=[[UITableViewCell alloc] init];
}
cell.backgroundColor=[UIColor clearColor];
UIButton *button_chaeckbox = [UIButton buttonWithType:UIButtonTypeCustom];
button_chaeckbox.backgroundColor=[UIColor clearColor];
button_chaeckbox.frame = CGRectMake(10, 10, 15, 15);
if( [checkedArray containsObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]])
{
[button_chaeckbox setBackgroundImage:[UIImage imageNamed:#"checked_checkbox.png"] forState:UIControlStateNormal];
}else
{
[button_chaeckbox setBackgroundImage:[UIImage imageNamed:#"empty_box_b.png"] forState:UIControlStateNormal];
}
[button_chaeckbox setTitle:#"creaButtonname" forState:UIControlStateNormal];
button_chaeckbox.tag=indexPath.row;
[button_chaeckbox addTarget:self
action:#selector(checkboxAction:)
forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:button_chaeckbox];
}
Please give me solution , i have try this code in ios 7 and ios 8 this is not working
Regards,
Nishant Chandwani
Do one thing give tag value for each button like
button_chaeckbox.tag=indexpath.row
in cellForRowAtIndexPath Method .
in checkboxAction do like this
NSString * titleText=sender.titleLabel.text
and you will check in button action method from which cell it is
like using conditions if(sender.tag == //your cell number second value//)
I think you want like this only .
Use this code for reuse cells in table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
cell=[[UITableViewCell alloc] init];
UILabel *fromLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 5, 250,20)];
cell.backgroundColor=[UIColor clearColor];
UIButton *button_chaeckbox = [UIButton buttonWithType:UIButtonTypeCustom];
button_chaeckbox.backgroundColor=[UIColor clearColor];
button_chaeckbox.frame = CGRectMake(10, 10, 15, 15);
[button_chaeckbox addTarget:self
action:#selector(checkboxAction:)
forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:button_chaeckbox];
button_chaeckbox.tag=1001;
}
if( [checkedArray containsObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]])
{
[button_chaeckbox setBackgroundImage:[UIImage imageNamed:#"checked_checkbox.png"] forState:UIControlStateNormal];
}else
{
[button_chaeckbox setBackgroundImage:[UIImage imageNamed:#"empty_box_b.png"] forState:UIControlStateNormal];
}
}
Use this code for get button from cell
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
UITableViewCell *cell = [tbl_view cellForRowAtIndexPath:indexPath];
UIButton *button_chaeckbox=(UIButton*)[cell viewWithtag:1001]
You can try this
In cellForRowAtIndexPath
[cell.button setTitle:#"RAM" forState:UIControlStateNormal];
cell.button.tag=indexPath.row;
[cell.button addTarget:self action:#selector(cellBtn:) forControlEvents:UIControlEventTouchUpInside];
Selector method
-(void)cellBtn :(UIButton *)sender
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
AlertCustomCell *cell = [tableview cellForRowAtIndexPath:indexPath];
NSString *user = cell.button.titleLabel.text;
NSLog(#"Text of button is :%#",user);
}
I hope it will work
let me point out one thing. if you want to traverse through all the subviews of the table cell you have to make for( UITableViewCell *getview in cell.subviews) to for( UIView *getview in cell.subviews)
The code would look like this
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
UITableViewCell *cell = [tbl_view cellForRowAtIndexPath:indexPath];
for( UIView *getview in cell.subviews)
{
if([getview isKindOfClass:[UIButton class]])
{
UIButton *button = (UIButton *)getView;
NSLog #("%#",button.titleLabel.text)
}
}
I would recommend making a UITableViewCell subclass and making the button a a property on that subclass. Then in your code would look something like this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
UILabel *fromLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 5, 250,20)];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.backgroundColor=[UIColor clearColor];
UIButton *button_chaeckbox = [UIButton buttonWithType:UIButtonTypeCustom];
button_chaeckbox.backgroundColor=[UIColor clearColor];
button_chaeckbox.frame = CGRectMake(10, 10, 15, 15);
if( [checkedArray containsObject:[NSString stringWithFormat:#"%ld",(long)indexPath.row]])
{
[button_chaeckbox setBackgroundImage:[UIImage imageNamed:#"checked_checkbox.png"] forState:UIControlStateNormal];
} else {
[button_chaeckbox setBackgroundImage:[UIImage imageNamed:#"empty_box_b.png"] forState:UIControlStateNormal];
}
[button_chaeckbox addTarget:self
action:#selector(checkboxAction:)
forControlEvents:UIControlEventTouchUpInside];
[cell setCellButton:button_chaeckbox];
return cell;
}
And then to get the button:
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:1 inSection:0];
CustomTableCell *cell = (CustomTableCell *)[tbl_view cellForRowAtIndexPath:indexPath];
UIButton * yourButton = cell.CellButton
my viewController contains a tableView where the user can add cells via coreData.
I defined the cells:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Travel";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSManagedObject *travel = [self.travelling objectAtIndex:indexPath.row];
UILabel *countryLabel = (UILabel *)[cell viewWithTag:101];
kategorieLabel.text = [travel valueForKey:#"country"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:#"button.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(15.0f, 32.0f, 24.0f, 20.0f);
[cell addSubview:button];
if ([[travel valueForKey:#"tick"] isEqualToString:#"yes"]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else{
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
}
- (void)buttonTapped:(UIButton *)sender {
UITableViewCell *owningCell = (UITableViewCell*)[sender superview];
[owningCell setAccessoryType:UITableViewCellAccessoryCheckmark];
NSIndexPath *indexPath = [_tableView indexPathForCell:owningCell];
NSManagedObject *travel = [self.travelling objectAtIndex:indexPath.row];
[travel setValue:#"yes" forKey:#"tick"];
}
When the user taps a button on the cell, the checkmark should appear. But when I reload or restart the app not all checkmarks are there. Maybe there is a better method to do this.
I have a grouped UITableView (this one has 4 sections) and several rows each. I have programatically created 2 buttons in each of the cells.
This is how I am creating the UITableViewCell. In this code, I am trying to detect the indexPath.row and the indexPath.section of the button that was pressed and pass it to the method. How am I able to do this ?
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellId = #"Cell";
UITableViewCell *cell ;//= [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
}
NSString *docTitle = [currentDocument objectForKey:#"displayname"];
UIView *cellView = [[UIView alloc] initWithFrame:CGRectMake(cell.contentView.frame.origin.x+5, cell.contentView.frame.origin.y, cell.contentView.frame.size.width, cell.contentView.frame.size.height)];
UILabel *cellTitle = [[UILabel alloc] initWithFrame:CGRectMake(cellView.frame.origin.x + 5, cellView.frame.origin.y + 5, cellView.frame.size.width - 10, 25)];
cellTitle.backgroundColor = [UIColor clearColor];
cellTitle.text = docTitle;
[cellView addSubview:cellTitle];
[cell.contentView addSubview:cellView];
UIButton *viewDocumentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[viewDocumentButton setTitle:#"View Online" forState:UIControlStateNormal];
viewDocumentButton.frame = CGRectMake(cellView.frame.origin.x + 5, cellTitle.frame.origin.y + cellTitle.frame.size.height + 5, 150, 35);
[viewDocumentButton addTarget:self action:#selector(openDocumentButtonPressedMethod:) forControlEvents:UIControlEventTouchDown];
[viewDocumentButton setTag:indexPath.row];
[cell.contentView addSubview:viewDocumentButton];
UIButton *downloadDocumentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[downloadDocumentButton setTitle:#"Download Document" forState:UIControlStateNormal];
downloadDocumentButton.frame = CGRectMake(cellView.frame.origin.x + 5, viewDocumentButton.frame.origin.y + viewDocumentButton.frame.size.height + 5, 150, 35);
[downloadDocumentButton addTarget:self action:#selector(openDocumentButtonPressedMethod:) forControlEvents:UIControlEventTouchDown];
[downloadDocumentButton setTag:indexPath.row];
[cell.contentView addSubview:downloadDocumentButton];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
Additionally, you could...
- (IBAction)openDocumentButtonPressedMethod:(id)sender {
UIButton *button = (UIButton *)sender;
UIView *contentView = button.superview;
UITableViewCell *cell = (UITableViewCell *)contentView.superview;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
// do something with the indexPath
}
And if you wanted to use the same method to handle both button events, then you could use the tag on the button to distinguish between the two buttons.
if (button.tag == 1) {
// do something with the indexPath view related
}
else {
// do something with the indexPath download related
}
Create a subclass of UIButton
#interface MyButton : UIButton
{ /* indexPath, other stuff */ }
#end
Then implement
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
to do something with the indexPath and other stuff before invoking the super for this method.
When you create the button, provide indexPath.
In your openDocumentButtonPressedMethod: method, do
CGPoint pointInTableView = [self.tableView convertPoint:sender.bounds.origin fromView:sender];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInTableView];
I have a UITableView with 20 rows. In each row, two UIButtons are added, so totally I have 40 buttons. How can I access each button in each cell? All those UIButton have the two tags 1 and 2.
For example: I want to write a method to change the background color of 2 buttons in a particular row:
-(void)changeColor:(int)row{
//code here
}
Do you have any suggestion?
-(UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"Cell"] autorelease];
UIButton *button1=[[UIButton alloc] initWithFrame:CGRectMake(x1,y1,w1,h1)];
UIButton *button2=[[UIButton alloc] initWithFrame:CGRectMake(x2,y2,w2,h2)];
[button1 setTag:1];
[button2 setTag:2];
[[cell contentView] addSubview:button0 ];
[[cell contentView] addSubview:button1 ];
[button0 release];
[button1 release];
}
UIButton *button1 = (UIButton *)[cell viewWithTag:1];
UIButton *button2 = (UIButton *)[cell viewWithTag:2];
return cell;
}
You should be able to do this:
-changeColor:(int)row
{
NSIndexPath indexPath = [NSIndexPath indexPathForRow:row inSection:0]; // Assuming one section
UITableViewCell *cell = [myTableView cellForRowAtIndexPath:indexPath];
UIButton *button1 = (UIButton *)[[cell contentView] viewWithTag:1];
UIButton *button2 = (UIButton *)[[cell contentView] viewWithTag:2];
}
*some syntax might be wrong. I dont have Xcode handy
If you want to change the button color to have a highlighted / downstate I suggest to use the following:
[yourButton addTarget:self action:#selector(goToView:) forControlEvents:UIControlEventTouchUpInside];
[yourButton addTarget:self action:#selector(changeColor:) forControlEvents:UIControlEventTouchDown];
[yourButton addTarget:self action:#selector(touchCancel:) forControlEvents:UIControlEventTouchDragExit];
-(void)buttonAction:(UIButton*)sender
{
[self touchCancel:sender];
/* DO SOME MORE ACTIONS */
}
-(void)changeColor:(UIButton*)sender
{
sender.backgroundColor = [UIColor redColor];
}
-(void)touchCancel:(UIButton*)sender
{
sender.backgroundColor = [UIColor clearColor];
}
If you want to make the button have a different selected color, create an array that holds all the selected states. Then use the array to check if the button color needs a different color in cellForRowAtIndexPath.
When you want to change the button color just change the value in the array and call
[self.tableView reloadData];
Be sure to do it outside the if (cell == nil) method so it is also called when the cell is reused.