iOS: UITableView reloadData not working - iphone

I have a UITableView with two sections: free and paid. Each section has a different kind of cell. The free cells have two labels and an image. The paid cells has two labels, an image and a button that allows the product to be bought. Once a product is bought, the BUY button on that particular cell must not be shown again. Said that, this is how the cells are initialized...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *IDNormal = #"Normal";
static NSString *IDComplex = #"Complex";
if (indexPath.section == 0) { // show free objects
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:IDNormal];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:IDNormal] autorelease];
// product description
UILabel * labelDescription = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 54.0, 225, 18)];
[labelDescription setTextAlignment:UITextAlignmentLeft];
[labelDescription setBackgroundColor:[UIColor whiteColor ]];
[labelDescription setClipsToBounds:YES];
[labelDescription setFont:[UIFont systemFontOfSize:14.0]];
[labelDescription setTextColor:[UIColor blackColor]];
[labelDescription setAlpha:0.6];
[labelDescription setTag: 860];
[cell addSubview:labelDescription];
[labelDescription release];
// this will show the word FREE on free objects (cells)
UILabel * labelFREE = [[UILabel alloc] initWithFrame:CGRectMake(235.0, 54.0, 80, 18)];
[labelFREE setTextAlignment:UITextAlignmentCenter];
[labelFREE setBackgroundColor:[UIColor greenColor ]];
[labelFREE setClipsToBounds:YES];
[labelFREE setFont:[UIFont boldSystemFontOfSize:14.0]];
[labelFREE setTextColor:[UIColor blackColor]];
[labelFREE setAlpha:0.75];
[labelFREE setText:NSLocalizedString(#"freeKey", #"")];
[labelFREE setTag: 861];
[cell addSubview:labelFREE];
[labelFREE release];
}
cell.imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat: #"free%d", indexPath.row] ofType:#"jpg"]];
NSString * prefixLabel = [NSString stringWithFormat: #"gratis%d", indexPath.row];
UILabel *labelDescription2 = (UILabel*)[cell viewWithTag:860];
[labelDescription2 setText:#"FREE"];
return cell;
} else { // show paid objects
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:IDComplex];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:IDComplex] autorelease];
UILabel * labelDescription = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 54.0, 225, 18)];
[labelDescription setTextAlignment:UITextAlignmentLeft];
[labelDescription setBackgroundColor:[UIColor whiteColor ]];
[labelDescription setClipsToBounds:YES];
[labelDescription setFont:[UIFont systemFontOfSize:14.0]];
[labelDescription setTextColor:[UIColor blackColor]];
[labelDescription setAlpha:0.6];
[labelDescription setTag: 1];
[cell addSubview:labelDescription];
[labelDescription release];
}
int numberPaidObject = indexPath.row + 500;
cell.imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat: #"table-pg%d", numberPaidObject] ofType:#"jpg"]];
NSString * nomeDoProduto = [NSString stringWithFormat: #"paid%d", numberPaidObject];
if ( NotSoldProduct ) {
NSString * prefixoEtiqueta = [NSString stringWithFormat: #"paid%d", numberPaidObject];
UILabel *labelDescription2 = (UILabel*)[cell viewWithTag:1];
[labelDescription2 setText:[description objectAtIndex: numberPaidObject ];
}
return cell;
}
}
as I have to identify which BUY button was clicked and I am using dequeueReusableCellWithIdentifier, so I have to use the following method...
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
int numeroOfPaidObject = indexPath.row + 500;
if ((indexPath.section == 1) && ObjectForSale) {
// if paid objects and object was not bought yet
// in theory this section will not be executed if the object was already bought and paid
// so, I am skipping the BUY button creation and, in theory the cell will not have a BUY
// button… the problem is that it does...
UIButton * buyButton = [[UIButton alloc] initWithFrame:CGRectMake( 235, 45, 80, 30)];
buyButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
buyButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[buyButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
buyButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
buyButton.backgroundColor = [UIColor clearColor];
[buyButton addTarget:self action:#selector(buyNow:) forControlEvents:UIControlEventTouchDown];
[buyButton setTitle:NSLocalizedString(#"buyKey", #"") forState:UIControlStateNormal];
UIImage *newImage = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
pathForResource: #"whiteButton" ofType:#"png"]]
stretchableImageWithLeftCapWidth:12.0f topCapHeight:0.0f];
[buyButton setBackgroundImage:newImage forState:UIControlStateNormal];
[buyButton setTag: numeroOfPaidObject];
[cell addSubview:buyButton];
[buyButton release];
}
}
The problem with this code is: when I reload table's data the BUY button continues to show up on all cells, including those that was already bought by the user.
Any ideas?
thanks for any help.

You can step through it with the debugger, but here is my guess:
Because table cells are being reused, eventually all of the already purchased items end up in table cells that were previously occupied by an unpurchased item and therefore have had a buy button added to them.
If this is the case you need to add an else clause in your second section of code that deletes the button from the cell if the product has already been purchased.
Another problem is that your code is adding a new button every time a cell is displayed, so many/most of your cells probably have several buttons in them.
You will want to refactor your code so that the button is added once, in tableView:cellForRowAtIndexPath:, and only for newly-created cells.
There are two ways to do that:
Split the "Complex" cell type into two types: purchased and unpurchased, and create/dequeue them separately. Add the button only to to the unpurchased cell type.
Add the buttons to all of the cells in the "paid" section, and hide it when the item has been purchased.
In either case you'll need a way to grab a pointer to the button. The preferred way to do this is with the tag property, making it a one liner:
UIButton * button = [cell viewForTag:42];
...
You can also iterate through the subviews of the cell looking for UIButton objects:
UIButton *button = nil;
foreach (UIView *view in cell.subviews) {
if ([view isKindOfClass:[UIButton class]])
button = (UIButton *)view;
}
I would suggest using a constant tag to identify the button, and then rewrite your buyNow: method as follows:
-(IBAction)buyNow:(id)sender {
UITableViewCell *cell = (UITableViewCell *)((UIView *)sender).superview;
int itemID = [tableView indexPathForCell:cell].row + 500;
...
}

Perhaps I am thinking too simply here but a table view will function just fine with only the delegates set, but will fail to respond to reloadData if you have not made the connection in IB, did you check that?

Related

UIImageView in UITableView cell content view is not updating

In my iPhone application, I have a UITableView and this contains a UIImageView, button and Label. I am updating my database as per the values from the server and updating the details in the tableview. If I run the app for second time, after some modification at the server, the imageview is not getting updated. Button and label are updating. When I checked the local path for the image from the database, it shows the new image in the documents folder but the table cell still shows the old one. To the see the updated image, I should reinstall the app. What should I do to fix this issue?
Here is the work flow of what I did:
Loading new values from the database, and keeping all the values in an array
Removing the tableview
Creating the tableview again
Reload tableview.
Edit
//creating custom cell for the table view for displaying different objects
- (UIMenuItemCell *) getCellContentView:(NSString *)cellIdentifier {
CGRect CellFrame = CGRectMake(0, 0, 150, 60);
CGRect Label1Frame = CGRectMake(20, 23, 98, 30);
CGRect imgFrame = CGRectMake(20, 48, 110, 123);
CGRect btnFrame = CGRectMake(25, 136, 100, 30);
UILabel *lblTemp;
UIImageView *itemImg;
UIButton *itemBtn;
UIMenuItemCell *cell = [[UIMenuItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.frame = CellFrame;
//Initialize Label with tag 1.
lblTemp = [[UILabel alloc] initWithFrame:Label1Frame];
lblTemp.tag = 1;
lblTemp.textColor=[UIColor colorWithRed:139.0f/255.0f green:69.0f/255.0f blue:19.0f/255.0f alpha:1.0f];
lblTemp.textAlignment = UITextAlignmentCenter;
lblTemp.backgroundColor = [UIColor clearColor];
lblTemp.font = [UIFont systemFontOfSize:13.0];
[cell.contentView addSubview:lblTemp];
[lblTemp release];
//Initialize ImageView
itemImg = [[UIImageView alloc]initWithFrame:imgFrame];
itemImg.tag = 2;
[cell.contentView addSubview:itemImg];
[itemImg release];
//Initialize Button
itemBtn = [[UIButton alloc]initWithFrame:btnFrame];
itemBtn.frame = btnFrame;
itemBtn.tag = 3;
itemBtn.titleLabel.textColor = [UIColor blueColor];
itemBtn.titleLabel.font = [UIFont systemFontOfSize:9.0];
[cell.contentView addSubview:itemBtn];
[itemBtn release];
return cell;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d", indexPath.row];
UIMenuItemCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [self getCellContentView:CellIdentifier];
cell.transform = CGAffineTransformMakeRotation(M_PI_2);
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.cellItemName = (UILabel *)[cell viewWithTag:1];
cell.cellitemImage = (UIImageView *)[cell viewWithTag:2];
cell.cellItemButton = (UIButton *)[cell viewWithTag:3];
DataBaseClass *itemObj = [appDelegate.itemArray objectAtIndex:indexPath.row];
NSString *imageLocalFilePath = nil;
if ([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:#"NotAvailable"]) {
cell.cellItemProgress.hidden = YES;
cell.cellItemButton.hidden = NO;
imageLocalFilePath = [NSString stringWithFormat:#"%#",[tempItemLocalNotAvailPath objectAtIndex:indexPath.row]];
NSString *date = [self changeDateFormat:itemObj.itemReleaseDate];
[cell.cellItemButton setTitle:date forState:UIControlStateNormal];
cell.cellItemButton.userInteractionEnabled = NO;
cell.userInteractionEnabled = NO;
[cell.cellItemButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:#"not_available_bttn_bck_img"] forState:UIControlStateNormal];
}else if ([[tempitemStatusArray objectAtIndex:indexPath.row] isEqualToString:#"Available"]){
cell.cellItemButton.userInteractionEnabled = YES;
cell.userInteractionEnabled = YES;
cell.cellItemProgress.hidden = YES;
[cell.cellItemButton setTitle:#"" forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:#"available_bttn_img_normal"] forState:UIControlStateNormal];
[cell.cellItemButton setBackgroundImage:[UIImage imageNamed:#"available_bttn_img_pressed"] forState:UIControlStateHighlighted];
[cell.cellItemButton removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.cellItemButton addTarget:self action:#selector(confirmationAlert:) forControlEvents:UIControlEventTouchUpInside];
imageLocalFilePath = [NSString stringWithFormat:#"%#",[tempItemLocalAvailPath objectAtIndex:indexPath.row]];
}
if ([imageLocalFilePath isEqualToString:#""]) {
[cell.cellitemImage setImage:[UIImage imageNamed:#"item01.png"]];
}else {
[cell.cellitemImage setImageWithURL:[NSURL fileURLWithPath:imageLocalFilePath] placeholderImage:[UIImage imageNamed:#"item01.png"]];
}
cell.cellItemName.text = [NSString stringWithFormat:#"%#",[tempItemNameArray objectAtIndex:indexPath.row]];
}
return cell;
}
Please help.
I found the issue, in the cellForRowAtIndexPath method, for setting the image, I used the code
[cell.cellitemImage setImageWithURL:[NSURL fileURLWithPath:imageLocalFilePath] placeholderImage:[UIImage imageNamed:#"item01.png"]];
I used a external classes calls ImageLoading for loading the images and that classes included some cache methods, and that caused the issue. So I changed that line to
[cell.cellitemImage setImage:[UIImage imageWithContentsOfFile:imageLocalFilePath]];
that solved the issue.
Thanks for your support :)
There should be a
}
after the line
cell.cellItemButton = (UIButton *)[cell viewWithTag:3];
i took jet a first look at your code, and i found out this "error":
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell%d", indexPath.row];
so... it won't give you any error, it works...
but that's against how table works:
doing this you are creating and allocating a new cell for each item of your array/database,
meaning that if you need to scroll to see 1.000 items, you create 1.000 cells!!!
it shouldn't be like this.
Normally a table just creates only the cells needed to be shown on the screen/display
meaning that if your table area is 300 pixel in height and each cell is 30 pixel height,
then you may need only 11 cells, and you should use/allocate only 11 cells, not 1.000
the magic of cells is to reuse cells when user scrolls them out of screen (e.g. UP), to set it's data and images with the new item data and to put it again on screen (e.g. DOWN)
thats what CellIdentifier is normally used for, and it should be the same for all cells in a table (at least if all cells are similar, but the contained data, and you don't need different cells)
allocating too many cells could give you memory problems, if you manage too much items...
p.s.
i'm probably not answering to your question, there may be other problems in your code, as i said i just read it in hurry
you will have to keep some time delay between laoding your data from databse and tableview reload. you will then able to see the updated image.

Unable to fetch the value from UITableViewCell by the self define methods

I am creating an app in which i have a UITableView and the table view each cell are having an UIView and the UIView contains two custom UIButton and two UILabel(all with same tag) the value of label coming from XML parsing. Now i have to do is that when i click any one button then it calls a method with the tag of the button then i want to fetch the value of the both labels of that cell and use that value.
But when i am doing this it is not happen by calling a method i am getting the tag value but when i try to get the label value then i am unable to get.
Is there any way to get the value of that?
Code of the method that i am using to get the label value...
-(void)swapButtonPressed:(id)sender {
NSInteger a= [sender tag];
UITableViewCell *cell;
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *) [[sender superview] superview]];
NSLog(#"%d", indexPath.row);
UIView *viewForCell = (UIView *)[cell.contentView viewWithTag:a];
UILabel *label = (UILabel *)[viewForCell viewWithTag:a];
NSString *str = label.text;
}
Code of the method cellForRowAtIndexPath....
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSDictionary *dict = [appDelegate.webDataList objectAtIndex:indexPath.row];
tableView.backgroundColor = [UIColor colorWithRed:0.39 green:0.39 blue:0.39 alpha:0.39];
if([appDelegate.dataArray count]>0){
imgView.backgroundColor = [UIColor clearColor];
imgView =[[UIView alloc ] initWithFrame:CGRectMake(0,0,320,45)];
imgView.tag= indexPath.row;
[cell.contentView addSubview:imgView];
button=[UIButton buttonWithType:UIButtonTypeCustom];
button.frame=CGRectMake(291, 5, 19, 21);
img =[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"swap_re" ofType:#"png"]];
[button setBackgroundImage:img forState:UIControlStateNormal];
[button addTarget:self action:#selector(swapButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
button.tag= indexPath.row;
[imgView addSubview:button];
button=[UIButton buttonWithType:UIButtonTypeCustom];
button.frame=CGRectMake(-25, 5, 19, 21);
img =[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"swap_re" ofType:#"png"]];
[button setBackgroundImage:img forState:UIControlStateNormal];
[button addTarget:self action:#selector(swapButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
button.tag= indexPath.row;
[imgView addSubview:button];
button=[UIButton buttonWithType:UIButtonTypeCustom];
button.frame=CGRectMake(5, 7, 19, 21);
button.tag = indexPath.row;
img =[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"delete" ofType:#"png"]];
[button setBackgroundImage:img forState:UIControlStateNormal];
[button addTarget:self action:#selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[imgView addSubview:button];
NSArray *arr = [[appDelegate.dataArray objectAtIndex:indexPath.row] componentsSeparatedByString:#"/"];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(34,9,140,20)];
label.text = [arr objectAtIndex:1];
label.tag = indexPath.row;
[label setFont:[UIFont fontWithName:#"Georgia" size:14]];
[label setNumberOfLines:0];
label.textAlignment = UITextAlignmentLeft;
label.textColor = [UIColor whiteColor];
label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
label.backgroundColor = [UIColor clearColor];
[imgView addSubview:label];
[label release];
label = [[UILabel alloc] initWithFrame:CGRectMake(181, 7, 75, 20)];
label.tag = indexPath.row;
label.text = [dict1 objectForKey:#"time"];
[label setFont:[UIFont fontWithName:#"Georgia" size:16.0]];
label.textAlignment = UITextAlignmentLeft;
[label setBackgroundColor:[UIColor clearColor]];
label.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
[label setTextColor:[UIColor whiteColor]];
[imgView addSubview:label];
[label release];
}
return cell;
}
I see two problems:
Tags need to be > 0 so you can't use indexPath.row directly.
Tags need to be unique within a superview
As #Kenny suggests, getting the indexPath from the cell and accessing the data source directly is generally more reliable. If you want to get values from the objects in the cell use unique tags > 0. I usually define an enum for tags within a subview to make things more readable.
I think that viewWithTag is recursive, so in your code that would mean that you get the label back in the first call to it, and nil in the second call. So perhaps this would work:
UILabel *label = (UILabel *)[cell.contentView viewWithTag:a];
NSString *str = label.text;
However, I'd recommend you get the value from your model object where you probably got it when you set the string on the button in the first place, something like this:
NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *) [[sender superview] superview]];
TheObect *obj = [myobjects objectAtIndex:indexPath.row];
NSString *string = obj.name;

add label on cell in table view and access it on buttonClicked Method.....:)

i am a new Programmer.... i wants add two labels on cell in table view.....and access the label.text in buttonClicked method.....
i am new programmer..so i don't know add label on table cell.... is I am right?
thanks in advance...for giving your valuable time for my code....:)
///insert individual row into the table view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"Cell %i",indexPath.section]];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:[NSString stringWithFormat:#"Cell %i",indexPath.section]] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;//my code.... change the color or selected cell
search_items *pro = [searchCount objectAtIndex:[indexPath row]];
/// i wants access these two labels on buttonClicked Method...
UILabel *showroomName = [[UILabel alloc] initWithFrame:anySize];
[showroomName setText:pro.s_showroomName];
[cell addSubview:showroomName];
[showroomName release];
UILabel *productName = [[UILabel alloc] initWithFrame:anySize];
[productName setText:pro.s_productName];
[cell addSubview:productName];
[productName release];
UIButton* aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
aButton.frame = CGRectMake(150, 15,150,40);
[aButton setTag:indexPath.row];
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:aButton];
UIImage *img = [UIImage imageNamed:#"image.png"];
[aButton setImage:img forState:UIControlStateNormal];
[aButton setTitle:#"View Details" forState:UIControlStateNormal];
[aButton addSubview:buttonLabel1];
NSString *filepath=[[NSBundle mainBundle]pathForResource:pro.s_image ofType:#"png"];
UIImage *image=[UIImage imageWithContentsOfFile:filepath];
cell.imageView.image=image;
return cell;
}
-(void)buttonClicked:(UIButton*)sender {
//int tag = sender.tag;
}
UILabel *showroomName = [[UILabel alloc] initWithFrame:anySize];
[showroomName setText:pro.s_showroomName];
cell.accessoryView = showroomName;
Try this for memory management: Alloc the label in a method that gets called a single time (like viewDidLoad, viewWillAppear, viewDidAppear, init, even numberOfSectionInTableView) and just change it's text or whatever you want to change in cellForRowAtIndexPath. This way, you will not have leaks, bad memory management or useless memory allocated. And also, be very careful with realeasing. You should release the objects when you are sure that you won't need those. Some objects might still need them after you release them.

Help me to get the IndexPath.row value

I have created a check box using the uiimageview and i have placed the checkbox into the uitableview cell like below
i want to get indexpath.row when i check the check box.
so i added the uiimageviiew inside the cell. so the didSelectRowAtIndexPath is gets called and gives me the indexpath.row.
but when the row is selected i want to show the detailed view.
now this runs me into trouble.
so can you people suggest me how to tackle my above problem.
when i check the checkbox i want to get the indexpath.row.
and when the row is selected i need to show the detailed view.
Thanks for your time and help
UPDATE 1 :
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
profileName = [appDelegate.archivedItemsList objectAtIndex:indexPath.row];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"xc"] autorelease];
cb = [[UIButton alloc] initWithFrame:CGRectMake(5,10, unselectedImage.size.width, unselectedImage.size.height)];
[cb setImage:unselectedImage forState:UIControlStateNormal];
[cb setImage:selectedImage forState:UIControlStateSelected];
[cb addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchDown];
[cell.contentView addSubview:cb];
}
if ( tableView == myTableView )
{
titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(60, 0, 150, 35)];
titleLabel.font = [UIFont boldSystemFontOfSize:13];
titleLabel.textColor = [UIColor blackColor];
[cell.contentView addSubview:titleLabel];
NSString *subjectData = [profileName.archive_subject stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
[titleLabel setText:[NSString stringWithFormat: #"%# ", subjectData]];
lblDescription = [[UILabel alloc]initWithFrame:CGRectMake(60, 30, 210, 30)];
lblDescription.numberOfLines = 2;
lblDescription.lineBreakMode = YES;
lblDescription.adjustsFontSizeToFitWidth = YES;
lblDescription.font = [UIFont systemFontOfSize:10];
lblDescription.textColor = [UIColor grayColor];
[cell.contentView addSubview:lblDescription];
NSString *CompanyName = [profileName.archive_content stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
[lblDescription setText:[NSString stringWithFormat: #"%# ", CompanyName]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
Use a UIButton instead of UIImageView for your checkbox - this way you can add an action/method to it, where you can grab the indexPath, plus you can add different images for selected/unselected state which will eliminate all the confusing stuff happening in your code above:
So in your cellForRowAtIndexPath: method:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
...// Your existing code here
UIImage *unselectedCheckboxImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"unselectedImageName" ofType:#"imageType"]];
UIImage *selectedCheckboxImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"selectedImageName" ofType:#"imageType"]];
UIButton *cb = [[UIButton alloc] initWithFrame:CGRectMake(desiredX, desiredY, unselectedCheckboxImage.frame.size.width, unselectedCheckboxImage.frame.size.height)];
[cb setImage:unselectedCheckboxImage forState:UIControlStateNormal];
[cb setImage:selectedCheckboxImage forState:UIControlStateSelected];
[cb addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchDown];
[cell.contentView addSubview:cb];
[cb release];
}
And then for your button action method:
- (IBAction)buttonAction:(id)sender
{
if ([sender isKindOfClass:[UIButton class]])
{
UIButton *checkboxButton = (UIButton*)sender;
checkboxButton.selected = !checkboxButton.selected;
NSIndexPath *indexPath = [self.myTableView indexPathForCell:(UITableViewCell*)[[checkboxButton superview] superview]];
// Do whatever you like here
}
}
I think your logic is causing the problem in the didSelectRowAtIndexPath: method; make sure that's right. Besides, if you just want to use check mark for the cell I think it's better if you use UITableViewCellAccessoryCheckmark. This may give you a basic idea.

IPHONE: UITableView cells not releasing content

I have this code below to populate my UITableView on the fly.
I have to display two kind of cells: a regular cell with a background image and a cell with a regular background image, plus a label and a button.
if Indexpath.row is less than a control variable, then regular cells are drawn. If not, cells with buttons and labels are drawn.
this is the code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
UIImage *imageU;
if (indexPath.row < controlVariable) {
imageU = [[[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat: #"table%d", indexPath.row] ofType:#"jpg"]] autorelease];
cell.imageView.image = imageU;
} else {
imageU = [[[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:[NSString stringWithFormat: #"table-pg%d",numberX]
ofType:#"jpg"]] autorelease];
cell.imageView.image = imageU;
NSString * myString = [NSString stringWithFormat: #"pago%d", numberX];
UILabel * myLabel = [[UILabel alloc] initWithFrame:CGRectMake(5.0, 49.0, 200.0, 22.0)];
[myLabel setTextAlignment:UITextAlignmentLeft];
[myLabel setBackgroundColor:[UIColor blueColor]];
[myLabel setClipsToBounds:YES];
[myLabel setFont:[UIFont systemFontOfSize:14.0]];
[myLabel setTextColor:[UIColor blackColor]];
[myLabel setText: myString];
[myLabel setAlpha:0.6];
[cell addSubview: myLabel];
[myLabel release];
UIButton *buyButton = [[UIButton alloc] initWithFrame:CGRectMake( 220, 4, 100, 35)];
buyButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
buyButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[buyButton setTitle:NSLocalizedString(#"buyKey", #"") forState:UIControlStateNormal];
[buyButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
buyButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
UIImage *newImage = [[[[UIImage alloc]initWithContentsOfFile:[[NSBundle mainBundle]
pathForResource: #"whiteButton" ofType:#"png"]] autorelease]
stretchableImageWithLeftCapWidth:12.0f topCapHeight:0.0f];
[buyButton setBackgroundImage:newImage forState:UIControlStateNormal];
[buyButton addTarget:self action:#selector(comprar:) forControlEvents:UIControlEventTouchDown];
buyButton.backgroundColor = [UIColor clearColor];
[buyButton setTag:indexPath.row];
[cell addSubview:buyButton];
[buyButton release];
}
return cell;
}
The problem with this code is: when I scroll the UITableView down and reach the division between regular cells and cells with buttons and labels, I see it is rendering correctly, but if I go up after going deep down, I see the buttons and labels being added to cells that were not supposed to have them. From this point forward, all cells contains buttons and labels...
It is like the cells are not releasing its contents before drawing. It is like labels and buttons are being added on top of other buttons and labels already on the cell. Cells are not releasing its contents before drawing again.
How to solve that?
thanks for any help.
NOTE: I see barely no difference after making the changes suggested by the two first answers. Now, not all cells are wrong, just some. They change every time I scroll down the table and return to the beginning of the table.
You should use a separate reuseIdentifier for each cell 'type' that you are using. In this case, you'll want to use two.
You'll also want to create/add the UILabel and UIButton when you get a dequeue miss and not for every run through.. In pseudocode:
UILabel * lbl;
UIButton * btn;
cell = [table dequeueReusableCellWithIdentifier:correctIdentifier];
if (cell == nil)
{
cell = ...; // alloc cell
lbl = ...;
lbl.tag = kTagLabel;
[cell addSubView:lbl];
btn = ...;
btn.tag = kTagButton;
[cell addSubView:btn];
}
else
{
lbl = (UILabel*)[cell viewWithTag:kTagLabel];
btn = (UIButton*)[cell viewWithTag:kTagButton];
}
//... now set the text/image appropriately.
Otherwise, you create a label and button each time the cell is dequeued from the table. Scrolling up and down will cause lots of labels and buttons to be created that never get released.
You should use two different reuseIdentifiers; one for cells with just images, and one for cells with images and buttons. The problem is that your one cell type is being reused, but its content is not (nor should it be) cleared out when it's dequeued.