In my cellForRowAtIndexPath, I'm doing some custom formatting on a subview for when that cell is selected. The complete function is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIView *left;
UIImageView *leftImage;
UILabel *label;
ArticleButton *btn;
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell)
{
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"UITableViewCell"] autorelease];
left = [[[UIView alloc] initWithFrame:CGRectMake(0, 2, 155, 139)] autorelease];
leftImage = [[[UIImageView alloc] initWithFrame:CGRectMake(7,9,141,77)] autorelease];
label = [[[UILabel alloc] initWithFrame:CGRectMake(6,87,141,48)] autorelease];
btn = [[[ArticleButton alloc] initWithFrame:CGRectMake(0,2,155,139)] autorelease];
left.tag = 0;
leftImage.tag = 1;
label.tag = 2;
btn.tag = 3;
[btn addTarget:self action:#selector(selectArticle:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:left];
[cell.contentView addSubview:leftImage];
[cell.contentView addSubview:label];
[cell.contentView addSubview:btn];
}
else
{
left = (UIView*)[cell viewWithTag:0];
leftImage = (UIImageView*)[cell viewWithTag:1];
label = (UILabel*)[cell viewWithTag:2];
btn = (ArticleButton*)[cell viewWithTag:3];
}
...load *entry
NSURL *url = [NSURL URLWithString:[entry imageUrl]];
FeedEntry* selectedEntry = [detailViewController detailItem];
NSString* selectedTitle = selectedEntry.title;
if ([selectedTitle isEqualToString:entry.title])
{
[left setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"cellbackground_sel.png"]]]; <-- PROBLEM IS THIS IMAGE NEVER CHANGES
NSLog(#"selected row %#", selectedTitle);
}
else{
[left setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"cellbackground2.png"]]];
}
[left setNeedsDisplay];
[leftImage setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeholder.gif"]];
[leftImage setContentMode:UIViewContentModeScaleAspectFill];
leftImage.clipsToBounds = YES;
[label setBackgroundColor:[UIColor clearColor]];
label.textColor = [UIColor whiteColor];
label.text = [entry.title stringByAppendingString:#"\n\n"];
label.numberOfLines = 3;
label.lineBreakMode = UILineBreakModeClip;
label.font = [UIFont fontWithName:#"Arial-BoldMT" size:12];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
The problem I'm having is with this section:
if ([selectedTitle isEqualToString:entry.title])
{
[left setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"cellbackground_sel.png"]]];
NSLog(#"selected row %#", selectedTitle);
}
else{
[left setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"cellbackground2.png"]]];
}
Everything else works, but although I'm logging that it gets called, but the background of my subview to indicate that the row in question is a selected row, never changes. I've tried calling setNeedsDisplay, I've tried scrolling up and down trying to get the cells to dequeue and get recreated, it just never users the other image, even though it logs that the row being drawn was a selected row.
(Once I get this working, I need to implement the "right" section to have two "cells" in the one row and only one will be selected. That's why I'm doing it this way with subviews in the cell).
What am I doing wrong?
I think it is a problem to set the tag to zero. The documentation says:
viewWithTag:
Return Value
The view in the receiver’s hierarchy whose tag property matches the value in the tag parameter.
Discussion
This method searches the current view and all of its subviews for the specified view.
If think that most views tag is zero, even that of the current cell's view. I think that you dont get the correct view out of it. Try not to use 0 as a tag to work with.
Whenever a particular UITableViewCell is selected, this particular delegate is called -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Try to see if your button taps are being first responded by this delegate rather than going to selectArticle: selector you have defined...
Instead of setting this in tableview:cellForRowAtIndexPath:, try doing it in the tableview:willSelectRowAtIndexPath:
See the protocol reference for further details.
Related
I am experiencing performance problems when using some subviews on my UITableViewCells. After I keep scrolling it eventually starts getting very slow.
First step I am doing is creating a common UIView for every cell, essentially this is creating a white cell with a rounded effect on the cell with a shadow. The performance for this seems to be normal so I don't think it's the culprit.
Here is the code I am using to do this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *NewsCellIdentifer = #"NewsCellIdentifier";
NewsItem *item = [self.newsArray objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NewsCellIdentifer];
cell.contentView.backgroundColor = [UIColor clearColor];
UIView *whiteRoundedCornerView = [[UIView alloc] initWithFrame:CGRectMake(10,10,300,100)];
whiteRoundedCornerView.backgroundColor = [UIColor whiteColor];
whiteRoundedCornerView.layer.masksToBounds = NO;
whiteRoundedCornerView.layer.cornerRadius = 3.0;
whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(-1, 1);
whiteRoundedCornerView.layer.shadowOpacity = 0.5;
[cell.contentView addSubview:whiteRoundedCornerView];
[cell.contentView sendSubviewToBack:whiteRoundedCornerView];
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
cell.layer.opaque = YES;
cell.opaque = YES;
}
[cell.contentView addSubview:[self NewsItemThumbnailView:item]];
return cell;
}
Here is the method that returns the thumbnail view of the graphic and text:
- (UIView *) NewsItemThumbnailView:(NewsItem *)item
{
UIView *thumbNailMainView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 50, 70)];
UIImageView *thumbNail = [[UIImageView alloc] initWithImage:[UIImage imageNamed:item.ThumbNailFileName]];
thumbNail.frame = CGRectMake(10,10, 45, 45);
UILabel *date = [[UILabel alloc] init];
date.frame = CGRectMake(10, 53, 45, 12);
date.text = item.ShortDateString;
date.textAlignment = NSTextAlignmentCenter;
date.textColor = [BVColors WebDarkGrey];
CGFloat fontSize = 10.0;
date.font = [BVFont Museo:&fontSize];
date.opaque = YES;
thumbNail.opaque = YES;
thumbNailMainView.opaque = YES;
[thumbNailMainView addSubview:thumbNail];
[thumbNailMainView addSubview:date];
return thumbNailMainView;
}
The performance problem seems to be when I add the thumbnail view to the cell because when I comment that line out, I don't seem to have it. The thumbnail information is dynamic and will change with each cell. I would appreciate any advice on how I should do this without degrading the performance.
UITableView will call tableView:cellForRowAtIndexPath: each time a cell comes into view, and dequeueReusableCellWithIdentifier: will reuse existing cell objects if they are available. These two facts combine to put you in a scenario where every time you scroll, the same finite number of cell objects end up with an increasing number of subviews.
The proper approach is to create a custom UITableViewCell subclass that has a property for thumbnailView. In the setter for that property, remove the previous thumbnail (if any) and then add the new one to the contentView. This ensures that you'll only ever have one thumbnail subview at any time.
A less optimal approach would be adding a tag to the UIView returned from NewsItemThumbnailView (thumbNailMainView.tag = someIntegerConstant) and then searching for any view with that tag and removing it before adding another:
// remove old view
UIView *oldThumbnailView = [cell.contentView viewWithTag:someIntegerConstant];
[oldThumbnailView removeFromSuperview];
// add new view
[cell.contentView addSubview:[self NewsItemThumbnailView:item]];
I ended up leveraging a solution found on this stackoverflow post:
How should I addSubview to cell.contentView?
Essentially when the cell is first initialized I am setting the view as mentioned by Nishant; however once the cell is reused I am extracting out the items I need to change, such as an UIImageView and then a UILabel. Since these are pointers I can modify just what I need when I need to and the performance is fast again. Here is a abbreviated version of what I did.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *NewsCellIdentifer = #"NewsCellIdentifier";
NewsItem *item = [self.newsArray objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer];
UIView *thumbNailMainView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 50, 70)];
UIImageView *thumbNail;
UIView *textMainView = [[UIView alloc] initWithFrame:CGRectMake(20,20,80,80)];
UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(52,-5, 70, 20)];
UILabel *teaserLabel = [[UILabel alloc] initWithFrame:CGRectMake(50,20, 210, 40)];
UIView *newsItemCornerMainView = [[UIView alloc] initWithFrame:CGRectMake(255.7, 55.2, 55, 55)];
UIImageView *cornerIconView;
// If the cell doesn't existing go ahead and make it fresh.
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NewsCellIdentifer];
// Configure all the various subviews
..... //Sample below
// Make the title view
headerLabel.text = item.Title;
CGFloat textfontSize = 16.0f;
headerLabel.font = [BVFont Museo:&textfontSize];
headerLabel.textColor = [BVColors WebBlue];
headerLabel.textAlignment = NSTextAlignmentLeft;
headerLabel.numberOfLines = 0;
headerLabel.tag = 50;
// Make the Teaser view
teaserLabel.text = item.Teaser;
teaserLabel.numberOfLines = 0;
CGFloat tfontSize = 13.0f;
teaserLabel.textAlignment = NSTextAlignmentLeft;
teaserLabel.textColor = [BVColors WebDarkGrey];
teaserLabel.font = [BVFont HelveticaNeue:&tfontSize];
[teaserLabel sizeToFit];
teaserLabel.tag = 51;
[textMainView addSubview:headerLabel];
[textMainView sendSubviewToBack:headerLabel];
[textMainView addSubview:teaserLabel];
[cell.contentView addSubview:textMainView];
....
}
thumbNail = (UIImageView *) [cell viewWithTag:47];
[thumbNail setImage:[UIImage imageNamed:item.ThumbNailFileName]];
headerLabel = (UILabel *) [cell viewWithTag:50];
headerLabel.text = item.Title;
teaserLabel = (UILabel *) [cell viewWithTag:51];
teaserLabel.text = item.Teaser;
cornerIconView = (UIImageView *) [cell viewWithTag:48];
[cornerIconView setImage:[UIImage imageNamed:item.CornerIconFileName]];
return cell;
}
You should change thumbNailMainView content only everytime but you should not add its content on cell everytime.
So add this line where you are allocating cell
[cell.contentView addSubview:[self NewsItemThumbnailView:item]];
add this inside braces. and then access thumbNailMainView from cell and pass that item data which you need to change for each cell.
Assign a tag to thumbNailMainView and its subview thumbNail then access it as
UIView *_thumbNailMainView = [cell.contentView viewWithTag:_thumbNailMainView_tag];
UIImageView *_thumbNail = [_thumbNailMainView viewWithTag:thumbNail_tag];
_thumbNail.image = [UIImage imageNamed:item.ThumbNailFileName];
Hope it helps you.
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.
I'm having a weird problem with my cells when it gets highlighted.
Just to introduce you better what the problem is, take a look at these two pictures:
This is how the cell looks like when it's not selected (normal state): http://cl.ly/0n193u3U1o403x1s0m3z
This is how the cell looks when it's highlighted (during tap): http://cl.ly/1o2U400D3L0b3n3m1N1J
As you can see, the background of the second label seems to get ignored when the cell is selected.
I don't want this to happen. I just want the 2nd label to stay there and remain as it is.
This is how I create the cells (there are several types each of them using different cell identifier).
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellTableIdentifier] autorelease];
cell.backgroundView = [[[UIView alloc] init] autorelease];
}
switch (indexPath.section) {
...
...
case kTableSectionPending:
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(10, 10, self.tableView.frame.size.width - 20, 30.0)] autorelease];
UILabel *label2 = [[[UILabel alloc] initWithFrame:CGRectMake(10, 50, self.tableView.frame.size.width - 20, 30.0)] autorelease];
label.text = NSLocalizedString(#"IncompletePath", #"");
label.font = [UIFont boldSystemFontOfSize:16];
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
label.layer.cornerRadius = 10;
FFRoute *lastPoint = ((FFRoute *) [[[FFSQLite sharedSingleton] getRoutesFromItinerary:itinerary] lastObject]);
label2.text = [NSString stringWithFormat:#"%#: %#", NSLocalizedString(#"LastPoint", #""), [self getStringFromTimestampOfFFRoute:lastPoint]];
label2.font = [UIFont systemFontOfSize:15];
label2.textAlignment = UITextAlignmentCenter;
label2.textColor = [UIColor whiteColor];
label2.backgroundColor = [UIColor colorWithRed:68/255.f green:82/255.f blue:124/255.f alpha:1];
label2.layer.cornerRadius = 10;
[label2 setOpaque:YES];
[cell.contentView addSubview:label];
[cell.contentView addSubview:label2];
// Set up background color
UIColor *bgcolor = [UIColor colorWithRed:250/255.f green:212/255.f blue:137/255.f alpha:1];
cell.backgroundView.backgroundColor = bgcolor;
break;
}
I tried to set to true the Opaque property with no luck.
What am I missing? Thank you
When you create the cell, do:
cell.selectionStyle = UITableViewCellSelectionStyleNone;
A cell can be highlighted, selected or both. You might want to customize your drawing so that it draws in a selected state (but draws as usual when only in highlighted state).
In iOS 6, you can use 2 methods in UITableViewDelegate to customise highlighting for the cell, and also its subviews:
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[cell setBackgroundColor:[UIColor lightGrayColor]]; // Your highlight color
// Make changes to subviews in cell
}
- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[UIView animateWithDuration:0.5f animations:^{
[cell setBackgroundColor:[UIColor whiteColor]]; // Your unhighlight
// Revert back changes for subviews
}];
}
hi all i implemented customized UITableViewcell with the below code.Each cell loaded with four images..
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *hlCellID = #"hlCellID";
UITableViewCell *hlcell = [tableView dequeueReusableCellWithIdentifier:hlCellID];
if(hlcell == nil) {
hlcell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:hlCellID] autorelease];
hlcell.accessoryType = UITableViewCellAccessoryNone;
hlcell.selectionStyle = UITableViewCellSelectionStyleNone;
[hlcell.contentView removeAllSubViews];
}
//NSLog(#"the scetions is %#",sections);
int section = indexPath.section;
for(int i=0;i<4;i++){
CGRect rect = CGRectMake(18+192*i, (4*indexPath.row)+50, 120, 150);
if ((4*indexPath.row)+i>=[self.imagesToDisplay count]) {
break;
}
UIImage *imageToDisplay=[UIImage imageWithData:[self.imagesToDisplay objectAtIndex:(4*indexPath.row)+i]];
NSLog(#"The size of the image is:%#",NSStringFromCGSize(imageToDisplay.size));
UIButton *button=[[UIButton alloc] initWithFrame:rect];
[button setFrame:rect];
[button setBackgroundImage:imageToDisplay forState:UIControlStateNormal];
[button setContentMode:UIViewContentModeCenter];
NSString *tagValue = [NSString stringWithFormat:#"%d%d",indexPath.row,i];
NSLog(#"the tag is %#",tagValue);
button.tag = [tagValue intValue];
NSLog(#"....tag....%d", button.tag);
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[hlcell.contentView addSubview:button];
[button release];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(18+192*i,(4*indexPath.row)+100+70 , 100, 100)] ;
label.text = #"price $0.99";
label.textColor = [UIColor blackColor];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.font = [UIFont fontWithName:#"ArialMT" size:12];
[hlcell.contentView addSubview:label];
[label release];
}
return hlcell;
}
for each image acts as uibutton.i am trying to load around 1000 images.these images i am taking from the server.when one image is loaded to my app i am updating total cell.
NSIndexPath *indexPath=[NSIndexPath indexPathForRow:ceil((float)[gridView.imagesToDisplay count]/4)-1 inSection:0];
NSArray *cellIndexPath=[NSArray arrayWithObjects:indexPath,nil];
[gridView.tableview reloadRowsAtIndexPaths:cellIndexPath withRowAnimation:UITableViewRowAnimationNone];
upto now my code is working fine and when i am trying to scroll many times after loading all the images its getting crash.and my GDB showing as memory warning.can any one suggest me why the issue happening.Thanks for your response in advance.
It looks like you always allocate new Images and display them on the Cell, but you never actually release the images when the cell is no longer displayed.
The definition for the UITableView cell states, that as soon a cell is no longer used it is purged and prepared for a new content. In your code you always add new subviews to the cell, but never actually release the content.
The best solution to your problem is to implement a UITableViewCell by subclassing it and manually set the images. Furthermore implement the
- (void)prepareForReuse
method of the class to release the images that are currently displayed. See the reference for more documentation of UITableViewCell
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.