Get row number of UITableView in IOS [duplicate] - iphone

This question already has answers here:
get section number and row number on custom cells button click?
(5 answers)
Closed 9 years ago.
In my code I have a table view with many sections sorted alphabetically. I have checkboxes(UIButton) in table rows and I need check them according to respective status entered in row. I had done
checkbutton.tag = indexpath.row;
but when table scrolls and section get changed and I get status of previous section in my checkbox method. anyone please help me on this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CheckButton = [UIButton buttonWithType:UIButtonTypeCustom];
[CheckButton addTarget:self action:#selector(CheckBoxAction:) forControlEvents:UIControlEventTouchUpInside];
CheckButton.tag=indexPath.row;
//some other stuff
[cell.contentView addSubview:CheckButton];
}
and this my CheckBoxAction
-(void)CheckBoxAction:(UIButton *)btn
{
tag = btn.tag;
NSDictionary *tagdict =[statusArray objectAtIndex:tag];
}
Now, problem is that indexpath.row is 0 whenever section is changed, so I can't able to access exact row number in my CheckBoxAction.

use this for getting current row you tap.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CheckButton = [[UIButton alloc] init];
[CheckButton addTarget:self action:#selector(CheckBoxAction:) forControlEvents:UIControlEventTouchUpInside];
CheckButton.tag=indexPath.row;
[cell addSubview:CheckButton];
}
-(void)CheckBoxAction:(id)sender
{
// Cast Sender to UIButton
UIButton *button = (UIButton *)sender;
// Find Point in Superview
CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];
// Infer Index Path
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:pointInSuperview];
// Log to Console
NSLog(#"selected Row : %d", indexPath.row);
}

// Try this
CheckButton.tag = [[NSString stringWithFormat:#"%d%d",indexPath.section,indexPath.row] integerValue];
or
// try this below link to get logic for, how to handle checkbox in UITableView
Set checkmark in UITableView

What you are doing is wrong in many ways. So, I am not going to give you a solution for the exact problem you have, but more of a guideline:
First you are adding the checkbox directly to the cell, which means you are possible adding multiple CheckButton to the same cell, if you scroll your UITableView a few times.
Add the checkButton on the cell directly instead of keep adding it in the cellForRowAtIndexPath, this can give you a performance boost.
Use a block that will be executed when a user clicks the button. This way you are able to capture the context of your UIViewController. You should assign that block to the cell on cellForRowAtIndexPath

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]);
}

Change a button dynamically in a table view cell

I have a table where 5 cells are there. In each cell there is a button. I need to change those buttons dynamically on some conditions. How to change the button dynamically in table view.
What you can do is Write a function which will change the values of the buttons and then you can call that function. After changing button values then use any one of the mentioned method below:
You can use either : [tableview reloadData]; to reload all the table data.
OR
You can reload particular rows using the following method :
[tableview reloadRowsAtIndexPaths: indexPath withRowAnimation:anyKindOfAnimation];
You can query your table view for all visible cells through -visibleCells, get the reference of your button (assuming you have a UITableViewCell subclass with a property for the button) and change them.
First you need to set tags for each buttons. This can be done by
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Your code
cell.Button.tag = indexPath.row;
[cell.Button addTarget:self action:#selector(buttonClick1:) forControlEvents:UIControlEventTouchUpInside];
}
Then you can get the button from this method
- (IBAction)buttonClick1:(id)sender {
int tagNo =[sender tag];
UITableViewCell *cellclicked = [self.tblProfileFollowing cellForRowAtIndexPath:[NSIndexPath indexPathForRow:tagNo inSection:0]];
//Now change the action for the cell
[cellclicked.Button addTarget:self action:#selector(buttonClick2:) forControlEvents:UIControlEventTouchUpInside];
//Your Code
}
You can follow the same steps for - (IBAction)buttonClick2:(id)sender
Now you can track which button was clicked and change the method for that button.
And declare your cell and button strong.

Create grid table view in iphone

I want to make a table view in which i want to show some items or images ( 4 items in a row)For eg: If i have 7 images i want to show 4 in first row and 3 in next row and if i have 13 images then it should display like 4,4,4,1 in rows 1,2,3,4 respectively. I have achievd this but my problem is those images keep changing their position (shift from 1 to 3 row and vice versa) when i scroll the table view. Please tell me some way so that my images automatically adjust themselves 4 in a row and does not repeat if i scroll the table view.
My code is:
(array has 7 image-datas stored in it)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 93;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Avi"];
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Avi"] autorelease];
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSData *imageData;
for(int i=0;i<4;i++){
imageData=[array objectAtIndex:indexpath.row];
UIButton *Button = [UIButton buttonWithType:UIButtonTypeCustom];
Button.frame = CGRectMake(5+(i*77), 5, 77,85);
[Button setBackgroundImage:[UIImage imageWithData:imageData] forState:UIControlStateNormal];
[cell.contentView addSubview:Button];
}
return cell;
So the code snippet you've posted isn't particularly helpful, but this almost certainly is a case of not recycling your table view cells properly.
Table views 'recycle' their cells for efficiency and performance - when a cell scrolls out of view it is marked for recycling: when you next request a new cell you will be given a recycled cell if one is available (otherwise a new cell will be created).
If all your cells use the same layout, this isn't a problem. However, if you adjust the layout of your cells (as you do) this can cause problems, because you might have set up a cell for 2-picture layout and have it be recycled for a 4-picture cell.
You have two options here: either take care to reset your cells as required (when you request a new cell reset all the view parameters you've created, which in your case would be by removing all the superviews), or create different cells with different identifiers for each of your layouts.
By the way, just looking at your current code it seems like you may want to consider some custom cells. Currently you add new images to the cell's contents view, which means since you never remove them every time your cell gets recycled more and more and more images get added! It's quite inefficient. Better to create a cell that has four image views ready to go, and you just assign the image property as required.

How to maintain a selected state, when clicks the UIButton in iPhone?

I have created three buttons and set the background image for the normal state and the selected state. When i click the button, changed one image as the selected state. But when is scroll the table view, the selected image is not retained (previous selected cell) which means it comes for the normal state.
My code is,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
likeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *likeSelectedImage = [UIImage imageNamed:#"like.png"];
//set image as background for button in the normal state
[likeBtn setBackgroundImage:likeSelectedImage forState:UIControlStateNormal];
[likeBtn addTarget:self action:#selector(likeAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:likeBtn];
}
My Button action is,
-(void) likeAction : (id) sender
{
UIImage *likeSelectedImg = [UIImage imageNamed:#"like-selected.png"];
UIImage *likeImg = [UIImage imageNamed:#"like.png"];
if ([sender isSelected]) {
[sender setImage:likeImg forState:UIControlStateNormal];
[sender setSelected:NO];
}else {
[sender setImage:likeSelectedImg forState:UIControlStateSelected];
[sender setSelected:YES];
}
}
SO my problem is, when i scroll the table view cell, the previously selected state of an image is not retained. Because the cellForRowAtIndex method has repeatedly called, when i scrolled the table. so it automatically sets "[likeBtn setBackgroundImage:likeSelectedImage forState:UIControlStateNormal];". How to avoid this problem?
So please help me out?
Thanks!
You are seeing this due to the design pattern that UITableView's use for displaying data. To minimize resource usage only the table cells that are currently on screen are guaranteed to be kept in memory. As cells are scrolled off-screen the cell objects are intended to be recycled to use for the new cell's appearing at the other end of the list and therefore lose their state.
I'm assuming you've trimmed your code somewhat as you're returning a cell in tableView: cellForRowAtIndexPath: but there's no reference to that variable anywhere else in the snippet you posted. This makes it impossible to see how you're getting the cell before adding the button.
Bit of a stab in the dark as to how your code works but here's a high level overview of what you need to do to retain state.
Create some controller-level storage such as an NSArray to hold all your button states for all the table rows.
In the likeAction determine which row the button is from (possibly assign the row number to the button's tag property when creating it) and update the state for the corresponding row in your NSArray
In tableView: cellForRowAtIndexPath: set up your button with the correct image by using the state which is fetched from the NSArray for the given indexPath.
the above one is not correct in syntax:
cell = [[[ToDoSummaryTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
give each cell a unique identifier, it should work.
See any sample code which uses 'reuseidentifier' in XCode IOS api.
Thanks,
Bharath
I re-edit your above code. I hope, I will help you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
likeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *likeSelectedImage = [UIImage imageNamed:#"like.png"];
//set image as background for button in the normal state
[likeBtn setBackgroundImage:likeSelectedImage forState:UIControlStateNormal];
[likeBtn setBackgroundImage:likeSelectedImage forState:UIControlStateHighlighted];
[likeBtn addTarget:self action:#selector(likeAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:likeBtn];
}
You can use 'reuseIdentifier' for each cell with an identifier.
cell = [[[ToDoSummaryTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:.<identifier>] autorelease];

Button placement on table footer view

I have a table view wherein the number cells are not fixed and will keep on changing. I have to show two action buttons after my last cell in the table footer. How can I place them properly after my last cell? I know the pixel spacing between last cell and these buttons. Any code sample will be really helpful.
Have you tried sticking them in a view and setting that as the footer view?
You need to give it the correct height before you add it; the width is automatically set to the width of the table. Either set it to a sensible width (e.g. 320) and use autoresizing or use a custom UIView subclass and implement -layoutSubviews.
You could always add two buttons to the final cell.
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
return [myCellDataArray count]+1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
if (indexPath.row > [myCellDataArray count]) {
cell = [tableView dequeueReusableCellWithIdentifier:#"Button Cell"];
if (cell == nil) {
UIButton *firstButton = [[UIButton alloc] init];
//customization
UIButton *secondButton = [[UIButton alloc] init];
//customization
[cell addSubView:firstButton];
[cell addSubView:firstButton];
}
} else {
// normal stuff
}
If you want to customize existing buttons you need to set it's tag to something unique, i.e. firstButton.tag = 100 and then set firstButton by firstButton = (UIButton *)[cell viewWithTag:100];. Make sure you define firstButton so that it's in scope!
Hope this helps!