UITableView overwriting - ios

I have a UITableView app that consists of text and images. The cells sometimes overwrite themselves and if I scroll the problem gets worse. See http://web-cars.com/images/temp_img/Simulator-Screen-Shot.png
I had the same problem in a previous app and a friend showed me how to resolve it by subclassing UITableViewCell. That was a text only app and I am unable to get the same solution with the images.
Here is my subclassed UITableViewCell:
-(void)prepareForReuse {
self.permLabel101.text = #"";
self.permUIImageView201.image = nil;
}
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
UILabel *label101 = [[UILabel alloc]initWithFrame:CGRectMake(5, 5, 310, 100)];
label101.tag = 101;
[label101 setLineBreakMode:NSLineBreakByWordWrapping];
[label101 setFont:[UIFont systemFontOfSize:FONT_SIZE]];
label101.textColor = [UIColor blackColor];
label101.backgroundColor = [UIColor clearColor];
label101.numberOfLines = 0;
self.permLabel101 = label101;
[self.contentView addSubview:self.permLabel101];
UIImageView *image201 = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 100)];
image201.tag = 201;
return self;
}
Here is my cellForRowAtIndexPath. I divide the text and images with photo_text.
- (MyTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObject *object = (NSManagedObject *)[entityArray objectAtIndex:indexPath.row];
NSString *CellIdentifier = #"Cell";
int photo_text = [[object valueForKey:#"photo_text"]intValue];
MyTableViewCell *cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MyTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.selectionStyle = UITableViewCellSeparatorStyleNone;
[self.tableView setSeparatorColor:[UIColor clearColor]]; // Eliminates border between cells
if (photo_text == 1) { // Image will be here
NSNumber *imgHeight = [[entityArray objectAtIndex:indexPath.row]valueForKey:#"imgHeight"];
float imgHeightFloat = [imgHeight floatValue];
NSLog(#"imgHeightFloat: %f", imgHeightFloat);
UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(0, 2, 320, imgHeightFloat)]; // imv is OK
UIImageView *image201View = [[UIImageView alloc]initWithFrame:CGRectMake(0, 2, 320, imgHeightFloat)];
imv.image = [UIImage imageNamed:[object valueForKey:#"photo"]];
image201View.image = [UIImage imageNamed:[object valueForKey:#"photo"]];
NSLog(#"Image cell: %#", cell);
NSString *title = [object valueForKey:#"title"];
self.title = title;
[cell.contentView addSubview:image201View];
return cell;
} else if (photo_text == 2) { // Text will be here
UILabel *label101;
cell.selectionStyle = UITableViewCellSeparatorStyleNone;
[self.tableView setSeparatorColor:[UIColor clearColor]]; // Eleminates border between cells
NSString *text = [object valueForKey:#"text"];
CGSize constraint = CGSizeMake(296.0f, 20000.0f);
CGSize size = [text sizeWithFont: [UIFont systemFontOfSize:12.0f] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
NSLog(#"Text cell: %#", cell);
label101 = (UILabel *)[cell viewWithTag:101];
label101.frame = CGRectMake(5, 5, 320, size.height);
label101.text = [NSString stringWithFormat:#"%#", text];
NSString *title = [object valueForKey:#"title"];
self.title = title;
return cell;
}
// Configure the cell...
// return cell;
}
Suggestions are appreciated!!

A friend was able to point me in the right direction.
My main problem was that I had a CellIdentifier conflict.
I had the following before my if statement separating the image and text cells:
NSString *CellIdentifier = #"cell";
And I needed to use different CellIdentifiers for the image and text cells:
NSString *CellIdentifier = #"cell";
and
NSString *CellIdentifier = #"cell2";
Also it turns out I did not need to place my UILabel and UIImageView in the subclassed UITableViewCell.
Finally, to get rid of a warning on cellForRowAtIndexPath: I needed
` return cell;
} else {
return nil;
}`

Related

UITableView cell are overlapping

I'm implementing a tableView with section index. where my tableViewCells are overlapping whenever the rows are more than one in any particular section.
Here is my code.
![- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return \[self.keys count\];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
// return \[\[\[UILocalizedIndexedCollation currentCollation\] sectionTitles\] objectAtIndex:section\];
return \[keys objectAtIndex:section\];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
// return \[\[UILocalizedIndexedCollation currentCollation\] sectionIndexTitles\];
return keys;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return \[\[UILocalizedIndexedCollation currentCollation\] sectionForSectionIndexTitleAtIndex:index\];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = \[tableView dequeueReusableCellWithIdentifier:nil\];
if (cell == nil) {
cell = \[\[UITableViewCell alloc\] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier\];
}
\[self.exhibitorTableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)\];
UIView* bgview = \[\[UIView alloc\] initWithFrame:CGRectMake(0, 0, 1, 1)\];
bgview.opaque = YES;
bgview.backgroundColor = \[UIColor colorWithRed:244.0f/255 green:245.0f/255 blue:246.0f/255 alpha:1.0\];
\[cell setBackgroundView:bgview\];
cell.textLabel.font = \[UIFont fontWithName:#"Roboto-Light" size:17\];
cell.detailTextLabel.font = \[UIFont fontWithName:#"Roboto-Light" size:13\];
cell.textLabel.backgroundColor = \[UIColor clearColor\];
cell.detailTextLabel.backgroundColor = \[UIColor clearColor\];
cell.textLabel.textColor = \[UIColor colorWithRed:93.0f/255 green:94.0f/255 blue:94.0f/255 alpha:1.0\];
UIImageView *defaultImage = \[\[UIImageView alloc\]init\];
\[defaultImage setFrame:CGRectMake(5.0f, 5.0f, 40.0f, 40.0f)\];
\[cell addSubview:defaultImage\];
for (int i=0; i<\[self.exhibitorArray count\]; i++) {
NSString * string = \[\[self.exhibitorArray objectAtIndex:i\]valueForKey:#"name"\];
NSString *firstLetter = \[string substringToIndex:1\];
if (\[\[keys objectAtIndex:indexPath.section\] isEqualToString:firstLetter\] ) {
NSString *urlString = \[\[NSString alloc\]init\];
urlString = #"http://";
urlString = \[urlString stringByAppendingString:\[NSString stringWithFormat:#"%#",\[\[self.exhibitorArray objectAtIndex:i\]valueForKey:#"image"\]\]\];
NSLog(#"%#",urlString);
AsyncImageView *asyncImageView = \[\[AsyncImageView alloc\] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)\];
\[asyncImageView setBackgroundColor:\[UIColor clearColor\]\];
NSString *tmp_string = \[\[NSString alloc\]init\];
tmp_string = urlString;
\[asyncImageView loadImageFromURL:\[NSURL URLWithString:tmp_string\]\];
\[defaultImage addSubview:asyncImageView\];
defaultImage.contentMode = UIViewContentModeScaleAspectFit;
tmp_string = nil;
asyncImageView = nil;
defaultImage = nil;
NSString *name_string = \[\[NSString alloc\]init\];
name_string = \[\[self.exhibitorArray objectAtIndex:i\]valueForKey:#"name"\];
NSLog(#"%#",name_string);
UILabel *user_name = \[\[ UILabel alloc\]init \];
\[user_name setFrame:(CGRectMake(58, 5, 270, 25))\];
\[user_name setBackgroundColor: \[UIColor clearColor\]\];
\[user_name setText:name_string\];
\[user_name setFont:\[UIFont fontWithName:#"Roboto-Light" size:14\]\];
\[user_name setTextAlignment:NSTextAlignmentLeft\];
\[user_name setTextColor:\[UIColor colorWithRed:93.0f/255 green:94.0f/255 blue:94.0f/255 alpha:1.0\]\];
\[cell addSubview:user_name\];
user_name = nil;
}
}
\[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator\];
return cell;
}
They're not overlapping. You are adding an additional label each time the cell is used.
You need to only add one label to a cell and then reuse that label instead of adding a new one each time.
The same is true for the image views etc...
You're best solution is to use a custom UITableViewCell subclass... http://www.appcoda.com/customize-table-view-cells-for-uitableview/
Possible solution
Note: I don't like this because of the use of the tag property but it will get it done without subclassing UITableviewCell...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
UIImageView *defaultImageView;
UILabel *customLabel;
if (cell == nil) {
// create the cell and empty views ready to take the content.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
defaultImageView = //create the image view
defaultImageView.tag = 3;
[cell.contentView addSubview:defaultImageView];
customLabel = //create custom label
customLabel.tag = 4;
[cell.contentView addSubview:customLabel];
} else {
// get the views that have already been created
defaultImageView = [cell.contentView viewWithTag:3];
customLabel = [cell.contentView viewWithTag:4];
}
// now populate the views...
defaultImageView.image = someImage;
customLabel.text = #"Hello, world";
return cell;
}
This way you are only creating one label and one image view in the cell and then reusing it propelry.
Thats just because you are creating new labels on every cell datasource method just change
just alloc and add label in
if (cell == nil) {
cell = \[\[UITableViewCell alloc\] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier\];
**//Allocate label here and set tag**
UILabel *nameLabel = [[UILabel alloc] initwithframe];
[nameLabel setTag:212];
}
**get label here by tag and set text on it here.**
eg
UILabel *nameLabel = [cell viewWithTag:212];
Similarly add imageview inside condition and set images on that outside
Because of this line [cell addSubview:user_name]; It've added multiple times.To avoid this, try below:
UILabel *user_name = [[ UILabel alloc]init ];
user_name.tag = SomeTagValue;
.
.
.
.
UILabel *preView = [cell viewWithTag:SomeTagValue];
[preView removeFromSuperview];
[cell addSubview:user_name];
Change the line UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil]; with UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
Edit
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
UIView* bgview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
bgview.opaque = YES;
bgview.tag = 8888;
bgview.backgroundColor = [UIColor colorWithRed:244.0f/255 green:245.0f/255 blue:246.0f/255 alpha:1.0];
[cell setBackgroundView:bgview];
cell.textLabel.font = [UIFont fontWithName:#"Roboto-Light" size:17];
cell.detailTextLabel.font = [UIFont fontWithName:#"Roboto-Light" size:13];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor colorWithRed:93.0f/255 green:94.0f/255 blue:94.0f/255 alpha:1.0];
UIImageView *defaultImage = [[UIImageView alloc]init];
[defaultImage setFrame:CGRectMake(5.0f, 5.0f, 40.0f, 40.0f)];
defaultImage.contentMode = UIViewContentModeScaleAspectFit;
defaultImage.tag = 7777;
[cell.contentView addSubview:defaultImage];
UILabel *user_name = [[ UILabel alloc]init ];
user_name.tag = 9999;
[user_name setFrame:(CGRectMake(58, 5, 270, 25))];
[user_name setBackgroundColor: [UIColor clearColor]];
[user_name setFont:[UIFont fontWithName:#"Roboto-Light" size:14]];
[user_name setTextAlignment:NSTextAlignmentLeft];
[user_name setTextColor:[UIColor colorWithRed:93.0f/255 green:94.0f/255 blue:94.0f/255 alpha:1.0]];
[cell.contentView addSubview:user_name];
AsyncImageView *asyncImageView = [[AsyncImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)];
asyncImageView.tag = 6666;
[asyncImageView setBackgroundColor:[UIColor clearColor]];
[defaultImage addSubview:asyncImageView];
}
[self.exhibitorTableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
UIImageView *defaultImage = (UIImageView*)[cell.contentView viewWithTag:7777];
UILabel *user_name = (UILabel*)[cell.contentView viewWithTag:9999];
AsyncImageView *asyncImageView = (AsyncImageView*)[defaultImage viewWithTag:6666];
for (int i=0; i<[self.exhibitorArray count]; i++) {
NSString * string = [[self.exhibitorArray objectAtIndex:i]valueForKey:#"name"];
NSString *firstLetter = [string substringToIndex:1];
if ([[keys objectAtIndex:indexPath.section] isEqualToString:firstLetter] ) {
NSString *urlString ;
urlString = #"http://";
urlString = [urlString stringByAppendingString:[NSString stringWithFormat:#"%#",[[self.exhibitorArray objectAtIndex:i]valueForKey:#"image"]]];
NSLog(#"%#",urlString);
NSString *tmp_string = urlString;
[asyncImageView loadImageFromURL:[NSURL URLWithString:tmp_string]];
NSString *name_string = [[self.exhibitorArray objectAtIndex:i]valueForKey:#"name"];
NSLog(#"%#",name_string);
[user_name setText:name_string];
}
}
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
return cell;
}
You are adding both cell.TextLabel and another Label (Named: user_name). If you want a custom table cell with imageview and label you can see this.
As you can see in your output that label is overlapping. Its not the same label these are different labels in a cell. Hope this helps.. :)
Edit: Try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = \[tableView dequeueReusableCellWithIdentifier:nil\];
if (cell == nil) {
cell = \[\[UITableViewCell alloc\] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier\];
}
\[self.exhibitorTableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)\];
UIView* bgview = \[\[UIView alloc\] initWithFrame:CGRectMake(0, 0, 1, 1)\];
bgview.opaque = YES;
bgview.backgroundColor = \[UIColor colorWithRed:244.0f/255 green:245.0f/255 blue:246.0f/255 alpha:1.0\];
\[cell setBackgroundView:bgview\];
UIImageView *defaultImage = \[\[UIImageView alloc\]init\];
\[defaultImage setFrame:CGRectMake(5.0f, 5.0f, 40.0f, 40.0f)\];
\[cell addSubview:defaultImage\];
for (int i=0; i<\[self.exhibitorArray count\]; i++) {
NSString * string = \[\[self.exhibitorArray objectAtIndex:i\]valueForKey:#"name"\];
NSString *firstLetter = \[string substringToIndex:1\];
if (\[\[keys objectAtIndex:indexPath.section\] isEqualToString:firstLetter\] ) {
NSString *urlString = \[\[NSString alloc\]init\];
urlString = #"http://";
urlString = \[urlString stringByAppendingString:\[NSString stringWithFormat:#"%#",\[\[self.exhibitorArray objectAtIndex:i\]valueForKey:#"image"\]\]\];
NSLog(#"%#",urlString);
AsyncImageView *asyncImageView = \[\[AsyncImageView alloc\] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)\];
\[asyncImageView setBackgroundColor:\[UIColor clearColor\]\];
NSString *tmp_string = \[\[NSString alloc\]init\];
tmp_string = urlString;
\[asyncImageView loadImageFromURL:\[NSURL URLWithString:tmp_string\]\];
\[defaultImage addSubview:asyncImageView\];
defaultImage.contentMode = UIViewContentModeScaleAspectFit;
tmp_string = nil;
asyncImageView = nil;
defaultImage = nil;
NSString *name_string = \[\[NSString alloc\]init\];
name_string = \[\[self.exhibitorArray objectAtIndex:i\]valueForKey:#"name"\];
NSLog(#"%#",name_string);
UILabel *user_name = \[\[ UILabel alloc\]init \];
\[user_name setFrame:(CGRectMake(58, 5, 270, 25))\];
\[user_name setBackgroundColor: \[UIColor clearColor\]\];
\[user_name setText:name_string\];
\[user_name setFont:\[UIFont fontWithName:#"Roboto-Light" size:14\]\];
\[user_name setTextAlignment:NSTextAlignmentLeft\];
\[user_name setTextColor:\[UIColor colorWithRed:93.0f/255 green:94.0f/255 blue:94.0f/255 alpha:1.0\]\];
\[cell addSubview:user_name\];
user_name = nil;
}
}
\[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator\];
return cell;
}

ImageView with Reusable Cell

I have to create custom UITableView and generally cell has UIImageView, and two UILabel when image of UIImageView is depend upon content which i got from server. so some cell has image and some has no image.
Problem is that when i use reusability of cell then previous UIImageView's image remain as it.. how can i remove it and implement my content on cell proper way.
Following is mine code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *isImgOfTable = [[self.listOfEvents objectAtIndex:indexPath.row] objectForKey:#"EventImage"];
NSString *CellIdentifier = #"Cell";
//NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if([isImgOfTable length] > 0)
{
UIImageView *imgOfEvent = [[UIImageView alloc] init];
imgOfEvent.tag = 101;
[cell.contentView addSubview: imgOfEvent];
}
UILabel *lblEventTitle = [[UILabel alloc] init];
lblEventTitle.tag = 102;
[cell.contentView addSubview:lblEventTitle];
UILabel *lblDescription = [[UILabel alloc] init];
lblDescription.tag = 103;
[cell.contentView addSubview:lblDescription];
}
if([isImgOfTable length] > 0)
{
NSString *newPath = #"";
UIImageView *imgEvent = (UIImageView *) [cell.contentView viewWithTag:101];
imgEvent.userInteractionEnabled = YES;
newPath = [[GeneralClass getDocumentDirectory] stringByAppendingPathComponent:[[self.listOfEvents objectAtIndex:indexPath.row] objectForKey:#"EventImage"]];
imgEvent.frame = CGRectMake(mainX, 4, 45, 45);
imgEvent.backgroundColor = [UIColor colorWithRed:(187/255.f) green:(226/255.f) blue:(255/255.f) alpha:1.0f];
imgEvent.layer.cornerRadius = 7;
imgEvent.layer.borderColor = [UIColor colorWithRed:(224/255.f) green:(224/255.f) blue:(224/255.f) alpha:1.0f].CGColor;
imgEvent.layer.borderWidth = 1;
imgEvent.clipsToBounds = YES;
imgEvent.image = [UIImage imageWithContentsOfFile:newPath];
}
UILabel *lblEventTitle = (UILabel*) [cell.contentView viewWithTag:102];
.
.
// Code of UILabel *lblEventTitle
UILabel *lblEventDescription = (UILabel*) [cell.contentView viewWithTag:103];
.
.
// Code of UILabel *lblEventDescription
return cell;
}
NOTE: I must want to use reusability of cell. I dont want to fix such like
NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d", indexPath.section, indexPath.row];
And also i am not used UITableViewCell class so may be it is not possible to call/override prepareForReuse
Please give me you suggestion.
Check this code it help full to you.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *isImgOfTable = [[self.listOfEvents objectAtIndex:indexPath.row] objectForKey:#"EventImage"];
NSString *CellIdentifier = #"Cell";
//NSString *CellIdentifier = [NSString stringWithFormat:#"S%1dR%1d", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImageView *imgOfEvent = [[UIImageView alloc] init];
imgOfEvent.tag = 101;
[cell.contentView addSubview: imgOfEvent];
UILabel *lblEventTitle = [[UILabel alloc] init];
lblEventTitle.tag = 102;
[cell.contentView addSubview:lblEventTitle];
UILabel *lblDescription = [[UILabel alloc] init];
lblDescription.tag = 103;
[cell.contentView addSubview:lblDescription];
}
UIImageView *imgEvent = (UIImageView *) [cell.contentView viewWithTag:101];
imgEvent.hidden=YES;
if([isImgOfTable length] > 0)
{
NSString *newPath = #"";
imgEvent.hidden=NO;
imgEvent.userInteractionEnabled = YES;
newPath = [[GeneralClass getDocumentDirectory] stringByAppendingPathComponent:[[self.listOfEvents objectAtIndex:indexPath.row] objectForKey:#"EventImage"]];
imgEvent.frame = CGRectMake(mainX, 4, 45, 45);
imgEvent.backgroundColor = [UIColor colorWithRed:(187/255.f) green:(226/255.f) blue:(255/255.f) alpha:1.0f];
imgEvent.layer.cornerRadius = 7;
imgEvent.layer.borderColor = [UIColor colorWithRed:(224/255.f) green:(224/255.f) blue:(224/255.f) alpha:1.0f].CGColor;
imgEvent.layer.borderWidth = 1;
imgEvent.clipsToBounds = YES;
imgEvent.image = [UIImage imageWithContentsOfFile:newPath];
}
UILabel *lblEventTitle = (UILabel*) [cell.contentView viewWithTag:102];
.
.
// Code of UILabel *lblEventTitle
UILabel *lblEventDescription = (UILabel*) [cell.contentView viewWithTag:103];
.
.
// Code of UILabel *lblEventDescription
return cell;
}
Might i suggest subclassing UITableViewCell and using prepareForReuse
-(void)prepareForReuse
{
labelOne = #"Default text 1";
labelTwo = #"Default label 2";
[imageView setImage:nil]; //Or you could set a default image?
}

My UITableViewCell is reusing a previous cells UIImage

I have a UITable that reuses cells. Each cell has an image dependant on a condition. The correct images are always used however when cells are reused the old image is displayed behind the new one. I have tried to remove the uiimageview before adding a new subview however it has no effect.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
return cell;
}
Any help would be greatly appreciated?
The problem is each time cellForRowAtIndexPath: is called you create a new imageview.
I corrected your code as follows:
Here we create an imageView once for each new new cell and replace it's image every time cellForRowAtIndexPath: is called:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
UIImageView *achievImg = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
//New Cell ... Create Image view
achievImg = [[UIImageView alloc] init];
achievImg.tag = 10;
[cell.contentView addSubview:achievImg];
}
else{
//Old cell...get previously createdd imageview
achievImg = (UIImageView*)[cell.contentView viewWithTag:10];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
//You don't need this because it doesn't have a superview in the first place..it's new
//[achievImg removeFromSuperview];
return cell;
}
try like this,
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
}
return cell;
}
You are always adding the imageView to the contentView of the cell. If the cell is reused that will lead to multiple imageViews in cell.
You can give a tag to the imageView. Always check if there is a view will same tag in the contentView of cell. If not add the imageView.
UIImageView *achievImg = (UIImageView *)[cell.contentView viewWithTag:55];
if(!achievImg){
achievImg = [[UIImageView alloc] init];
achievImg.tag = 55;
[cell.contentView addSubView:achievImg];
}

UITableView dequeue not working as expected

As I scroll down the list, all the rows are there, but they keep adding more subviews the more they appear on the visible frame
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reuse = #"RuleCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuse];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:reuse];
}
NSUInteger row = indexPath.row;
[self createCell: cell onRow: row];
return cell;
}
- (void) createCell: (UITableViewCell*)cell onRow: (NSUInteger)row
{
UIImageView* bgImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cell_background_spade_active.png"]];
cell.backgroundView = bgImage;
cell.textLabel.hidden = YES;
UILabel* titleLabel = [[UILabel alloc] initWithFrame: CGRectMake(100, CGRectGetHeight(cell.frame) / 2, 200, 50)];
titleLabel.text = [[self.ruleList objectAtIndex: row] objectForKey: TitleKey];
titleLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview: titleLabel];
}
I think you need to execute almost all of the logic that's in createCell: only within the if (cell == nil){ segment of your code. The part that should execute where you're currently calling createCell: is just getting a reference to the titleLabel and setting its text value.
To clarify, here's the kind of modification I'm suggesting (not tested, but should give the right idea):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reuse = #"RuleCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuse];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:reuse];
[self setUpCell: cell];
}
NSUInteger row = indexPath.row;
UILabel *titleLabel = (UILabel *)[cell.contentView viewWithTag:42];
titleLabel.text = [[self.ruleList objectAtIndex: row] objectForKey: TitleKey];
return cell;
}
- (void) setUpCell: (UITableViewCell*)cell
{
UIImageView* bgImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cell_background_spade_active.png"]];
cell.backgroundView = bgImage;
cell.textLabel.hidden = YES;
UILabel* titleLabel = [[UILabel alloc] initWithFrame: CGRectMake(100, CGRectGetHeight(cell.frame) / 2, 200, 50)];
titleLabel.tag = 42;
titleLabel.backgroundColor = [UIColor clearColor];
[cell.contentView addSubview: titleLabel];
}

iOS create a invisible space between cells

I have a standard tableview here and I wanted to be able to add a space between each cell that is invisible/hidden that shows the background. What is the correct way of doing it?
Here is the code I am using:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
JointCAD *currentCall = [[xmlParser calls] objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
// Format each frame that holds each piece of content in each row
CGRect countyImageFrame = CGRectMake(275, 6, 18, 18);
UIImageView *countyImageLabel = [[UIImageView alloc] initWithFrame:countyImageFrame];
countyImageLabel.tag = 0016;
countyImageLabel.backgroundColor = BG_COLOR
[cell.contentView addSubview:countyImageLabel];
CGRect callTypeImageFrame = CGRectMake(275, 30, 18, 18);
UIImageView *callTypeImageLabel = [[UIImageView alloc] initWithFrame:callTypeImageFrame];
callTypeImageLabel.tag = 0017;
callTypeImageLabel.backgroundColor = BG_COLOR
[cell.contentView addSubview:callTypeImageLabel];
CGRect callTypeFrame = CGRectMake(5, 2, 175, 15);
UILabel *callTypeLabel = [[UILabel alloc] initWithFrame:callTypeFrame];
callTypeLabel.tag = 0011;
callTypeLabel.backgroundColor = BG_COLOR
callTypeLabel.numberOfLines = 2;
callTypeLabel.font = [UIFont boldSystemFontOfSize:12];
[cell.contentView addSubview:callTypeLabel];
CGRect locationFrame = CGRectMake(5, 21, 175, 10);
UILabel *locationLabel = [[UILabel alloc] initWithFrame:locationFrame];
locationLabel.tag = 0014;
locationLabel.backgroundColor = BG_COLOR
locationLabel.numberOfLines = 2;
locationLabel.font = [UIFont systemFontOfSize:10];
[cell.contentView addSubview:locationLabel];
CGRect unitsFrame = CGRectMake(3, 40, 175, 10);
UILabel *unitsLabel = [[UILabel alloc] initWithFrame:unitsFrame];
unitsLabel.tag = 0012;
unitsLabel.backgroundColor = BG_COLOR
unitsLabel.textColor = [UIColor blackColor];
unitsLabel.font = [UIFont italicSystemFontOfSize:10];
[cell.contentView addSubview:unitsLabel];
CGRect stationFrame = CGRectMake(185 , 28, 85, 20);
UILabel *stationLabel = [[UILabel alloc] initWithFrame:stationFrame];
stationLabel.tag = 0013;
stationLabel.backgroundColor = BG_COLOR
stationLabel.font = [UIFont boldSystemFontOfSize:12];
[cell.contentView addSubview:stationLabel];
CGRect callnumberFrame = CGRectMake(185 , 5, 80, 20);
UILabel *callnumberLabel = [[UILabel alloc] initWithFrame:callnumberFrame];
callnumberLabel.tag = 0015;
callnumberLabel.backgroundColor = BG_COLOR
callnumberLabel.font = [UIFont boldSystemFontOfSize:12];
[cell.contentView addSubview:callnumberLabel];
}
// Display content in each cell
if ([currentCall.county isEqualToString:#"W"]) {
UIImage *countyImage = [UIImage imageNamed:#"blue.png"];
UIImageView *countyImageLabel = (UIImageView *)[cell.contentView viewWithTag:0016];
countyImageLabel.image = countyImage;
}
else {
UIImage *countyImage = [UIImage imageNamed:#"green.png"];
UIImageView *countyImageLabel = (UIImageView *)[cell.contentView viewWithTag:0016];
countyImageLabel.image = countyImage;
}
if ([currentCall.callType isEqualToString:#"F"]) {
UIImage *callTypeImage = [UIImage imageNamed:#"red.png"];
UIImageView *callTypeImageLabel = (UIImageView *)[cell.contentView viewWithTag:0017];
callTypeImageLabel.image = callTypeImage;
}
else {
UIImage *callTypeImage = [UIImage imageNamed:#"yellow.png"];
UIImageView *callTypeImageLabel = (UIImageView *)[cell.contentView viewWithTag:0017];
callTypeImageLabel.image = callTypeImage;
}
UILabel *callTypeLabel = (UILabel *)[cell.contentView viewWithTag:0011];
callTypeLabel.text = [currentCall currentCallType];
UILabel *locationLabel = (UILabel *)[cell.contentView viewWithTag:0014];
locationLabel.text = [currentCall location];
UILabel *unitsLabel = (UILabel *)[cell.contentView viewWithTag:0012];
unitsLabel.text = [currentCall units];
NSString *station = [#"Station: " stringByAppendingString:currentCall.station];
UILabel *stationLabel = (UILabel *)[cell.contentView viewWithTag:0013];
stationLabel.text = station;
NSString *callnumber = [#"Call No: " stringByAppendingString:currentCall.callnumber];
UILabel *callnumberLabel = (UILabel *)[cell.contentView viewWithTag:0015];
callnumberLabel.text = callnumber;
cell.backgroundColor = BG_COLOR
return cell;
}
// Set how tall each cell is
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 55;
}
Let me start by saying I did not read all your code. That said I have done exactly this. The first approach is to declare in the heightForCell a larger value for the cell above where the gap should be. The cell.contentView might need to have its clipToBounds set. I believe in this case the cell size should be set by setting the cell.frame.size (the origin is 0,0), and the contentsView and backgroundview properly sized too.
The second way to do it is to insert empty cells - cells with a different reuse identifier, and which are just empty cells with everything set to have a clear color.
Just use the trick to have spaces between each cells..
static NSString *CELL_ID2 = #"SOME_STUPID_ID2";
// even rows will be invisible
if (indexPath.row % 2 == 1)
{
UITableViewCell * cell2 = [tableView dequeueReusableCellWithIdentifier:CELL_ID2];
if (cell2 == nil)
{
cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CELL_ID2];
[cell2.contentView setAlpha:0];
[cell2 setUserInteractionEnabled:NO]; // prevent selection and other stuff
}
return cell2;
}
I just use different heights and alternate colours between cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
if (indexPath.row % 2 == 1)
{
static NSString *CellIdentifier = #"cellID1";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
cell.backgroundColor = [UIColor colorWhite];
return cell;
} else {
static NSString *CellIdentifier2 = #"cellID2";
UITableViewCell *cell2 = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell2 == nil) {
cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier2];
}
cell2.backgroundColor = [UIColor clearColor];
return cell2;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row % 2 == 1) {
return 40.0;
} else {
return 2.0;
}
}

Resources