I have created a uitableview with preloaded XML titles and I am looking to add images to the left of the text designed to display videos. This is what I have so far:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Get cell
static NSString *CellIdentifier = #"CellA";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// Display
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.font = [UIFont systemFontOfSize:15];
if (item) {
// Item Info
NSString *itemTitle = item.title ? [item.title stringByConvertingHTMLToPlainText] : #"[No Title]";
// Display
switch (indexPath.section) {
case SectionHeader: {
// Header
switch (indexPath.row) {
case SectionHeaderTitle:
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
cell.textLabel.text = itemTitle;
break;
case SectionHeaderDate:
cell.textLabel.text = dateString ? dateString : #"[No Date]";
break;
case SectionHeaderURL:
cell.textLabel.text = #"View Full Website";
cell.textLabel.textColor = [UIColor blueColor];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
break;
case SectionHeaderEnclosure:
cell.textLabel.text = #"Video";
cell.textLabel.textColor = [UIColor blackColor];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.imageView.image = [UIImage imageNamed:#"MovieFolder.png"];
break;
}
break;
}
case SectionDetail: {
// Summary
cell.textLabel.text = summaryString;
cell.textLabel.numberOfLines = 0; // Multiline
break;
}
}
}
return cell;
}
I thought I was doing it right, but the image does not show up. What should I do?
Related
I have a TableView with Static Cells with a header which has 4 Cells, one cell in the middle carries a UIWebView and as footer a section with comments. Each comment has it's own cell.
My Problem is if the Footer has 4 or more comments, the 4th cell in the footer carries the same UIWebView as the cell in the middle.
My cellForRowAtIndexPath looks like this:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Get cell
static NSString *CellIdentifier = #"CellA";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
UITableViewCell *contentCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (contentCell == nil) {
contentCell = [[CustomDetailTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Display
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.font = [UIFont systemFontOfSize:15];
if (item) {
// Item Info
NSString *itemTitle = item.title ? [item.title stringByConvertingHTMLToPlainText] : #"[No Title]";
// Display
switch (indexPath.section) {
case SectionHeader: {
// Header
switch (indexPath.row) {
case SectionHeaderTitle:
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
cell.textLabel.text = itemTitle;
cell.textLabel.numberOfLines = 0; // Multiline
break;
case SectionHeaderDate:
cell.textLabel.text = dateString ? dateString : #"[Kein Datum]";
cell.imageView.image = nil;
break;
case SectionHeaderSharerFacebook:
cell.textLabel.text = #"Share on Facebook";
cell.imageView.image = [UIImage imageNamed:#"f_logo.png"];
break;
case SectionHeaderSharerTwitter:
cell.textLabel.text = #"Share on Twitter";
cell.imageView.image = [UIImage imageNamed:#"twitter-bird-blue-on-white.png"];
}
break;
}
case SectionDetail: {
//add webView to your cell
if (webViewDidFinishLoad == TRUE && indexPath.section != SectionComments) {
CGFloat contentHeight = webView.scrollView.contentSize.height;
webView.frame = CGRectMake(23, 10, 275, contentHeight);
} else {
webView.frame = CGRectMake(23, 10, 275, 10);
}
cell.backgroundColor = [UIColor whiteColor];
[cell addSubview:webView];
break;
}
case SectionComments: {
NSString *writerText = [[[self.commentParser.commentsArray objectAtIndex:indexPath.row] name] stringByAppendingString:#" schrieb:\n"];
writerText = [writerText stringByAppendingString:[[self.commentParser.commentsArray objectAtIndex:indexPath.row] description]];
writerText = [writerText stringByAppendingFormat:#"\n"];
cell.textLabel.text = writerText;
cell.imageView.image = nil;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0; //multiline
if (cell.textLabel.text == nil) {
cell.textLabel.text = #"Keine Kommentare vorhanden";
cell.textLabel.font = [UIFont fontWithName:#"Verdana-Italic" size:12];
}
break;
}
}
return cell;
}
}
Why is the UIWebView in the 4th cell again, and how can I change that ?
Thanks for every answer!
The reason is UITableView reuses it's cells to conserve memory. There are tons of questions on this topic, I would recommend that you read some (1, 2, ...). Briefly, when you do:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
for a cell in footer section, you get a cell which was previously in the middle section that contains a UIWebView. You need to remove the UIWebView subview before you reuse it as a cell in footer section.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
// NSLog(#"msgcnt123 %#\n",[messageCount objectAtIndex:indexPath.row]);
NSArray *seperateArray = [[clist objectForKey:[[clist allKeys]objectAtIndex:indexPath.row]]componentsSeparatedByString:#"#"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// NSLog(#"key %#\n",[[clist allKeys]objectAtIndex:indexPath.row]);
cell.textLabel.text = [seperateArray objectAtIndex:0];
// cell.textLabel.text = [contactlist objectAtIndex:indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// NSLog(#"sep %#\n",seperateArray);
if (![[seperateArray objectAtIndex:1] isEqualToString:#"0"]) {
NSLog(#"msgCount %#\n",[seperateArray objectAtIndex:1]);
lblCnt = [[UILabel alloc]initWithFrame:CGRectMake(260, 13, 20, 20)];
lblCnt.backgroundColor = [UIColor lightGrayColor];
lblCnt.textColor = [UIColor blackColor];
lblCnt.text = [seperateArray objectAtIndex:1];
lblCnt.textAlignment = UITextAlignmentCenter;
lblCnt.layer.masksToBounds = YES;
lblCnt.layer.cornerRadius = 2.0f;
[cell.contentView addSubview:lblCnt];
}
else
{
NSLog(#"msgCount1 %#\n",[seperateArray objectAtIndex:1]);
[lblCnt removeFromSuperview];
lblCnt.hidden = YES;
}
return cell;
}
I have added a label in each row which displays number of messages received.In didSelect method i make label count zero so i can disappear label from tableView.In case of more than one row in table view label not disappear.
The simple and dirty method to reach what u want is to use a tag
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
NSArray *seperateArray = [[clist objectForKey:[[clist allKeys]objectAtIndex:indexPath.row]]componentsSeparatedByString:#"#"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [seperateArray objectAtIndex:0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (![[seperateArray objectAtIndex:1] isEqualToString:#"0"]) {
lblCnt = [[UILabel alloc]initWithFrame:CGRectMake(260, 13, 20, 20)];
lblCnt.backgroundColor = [UIColor lightGrayColor];
lblCnt.textColor = [UIColor blackColor];
lblCnt.text = [seperateArray objectAtIndex:1];
lblCnt.textAlignment = UITextAlignmentCenter;
lblCnt.layer.masksToBounds = YES;
lblCnt.layer.cornerRadius = 2.0f;
[cell.contentView addSubview:lblCnt];
//Add a tag
lblCnt.tag = 1000;
}
else
{
/*
NSLog(#"msgCount1 %#\n",[seperateArray objectAtIndex:1]);
[lblCnt removeFromSuperview];
lblCnt.hidden = YES;
*/
for (UIView *view in [cell.contentView subviews]) {
if (view.tag == 1000) {
[view removeFromSuperview];
}
}
}
return cell;
}
and select the view based on the tag.
I'm developing an iPhone Application, and I have a small issue, or so I think. I have a tableview and I got it to set the colors and labels of the cells by returning the cells in a method. Everything seems fine when I run it, the problem is when I scroll the cell's color changes to that of the cell below or above. I'm not sure how to solve this. I believe it's updating the cell when I scroll for some reason. How would I change this to only set the cell properties at first and not when I scroll?
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
tableCellCount ++;
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier];
UIColor * lightRed = [UIColor colorWithRed:0.6 green:0.1 blue:0 alpha:1.0];
UIColor * darkRed = [UIColor colorWithRed:0.7 green:0.1 blue:0 alpha:1.0];
UIColor * darkGray = [UIColor colorWithRed:0.15 green:0.15 blue:0.15 alpha:1.0];
NSLog(#"A");
if (tableCellCount % 2 == 0) {
cell.contentView.backgroundColor = darkRed;
cell.detailTextLabel.backgroundColor = darkRed;
cell.textLabel.backgroundColor = darkRed;
} else {
cell.contentView.backgroundColor = lightRed;
cell.detailTextLabel.backgroundColor = lightRed;
cell.textLabel.backgroundColor = lightRed;
}
cell.textLabel.textColor = [UIColor whiteColor];
UIView *bgColorView = [[UIView alloc] init];
[bgColorView setBackgroundColor:darkGray];
[cell setSelectedBackgroundView:bgColorView];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
}
Update
I figured out the solution to my problem.
Here's the updated code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[[content objectAtIndex:indexPath.section] objectForKey:#"rowValues"]
objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:#"News_Icon#2x.png"];
UIColor * lightRed = [UIColor colorWithRed:0.7 green:0.1 blue:0 alpha:1.0];
UIColor * darkRed = [UIColor colorWithRed:0.6 green:0.1 blue:0 alpha:1.0];
UIColor * darkGray = [UIColor colorWithRed:0.15 green:0.15 blue:0.15 alpha:1.0];
if (row % 2 == 0) {
cell.contentView.backgroundColor = darkRed;
cell.detailTextLabel.backgroundColor = darkRed;
cell.textLabel.backgroundColor = darkRed;
} else {
cell.contentView.backgroundColor = lightRed;
cell.detailTextLabel.backgroundColor = lightRed;
cell.textLabel.backgroundColor = lightRed;
}
cell.textLabel.textColor = [UIColor whiteColor];
UIView *bgColorView = [[UIView alloc] init];
[bgColorView setBackgroundColor:darkGray];
[cell setSelectedBackgroundView:bgColorView];
for(UIView *view in [tableView subviews]) {
if([[[view class] description] isEqualToString:#"UITableViewIndex"]) {
[view setBackgroundColor:[UIColor clearColor]];
}
}
return cell;
}
For each cell in the table, there are properties you want to set the first time only when the cell gets created and there are other properties you want to set each time.
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:anyId];
if(cell==nil)
{
// Properties to set the first time when the cell is created only
}
// Properties to set each time
return cell;
You are reusing cell views. Check the method in your table view controller tableView:cellForRowAtIndexPath:and you for sure are using dequeueReusableCellWithIdentifier:. You have to set color values to that reused cell.
You have a problem with cells being reused. UITableViews recycle cells. So if you are not correctly handling this in your tableview:cellForRowAtIndex: method you will get strange results when you scroll. Always assume that the cell you are setting up may already be setup as another cell.
I know that if I have some images and subviews added in customized cell then I have to reuse the cell so that custom control won't appear on other cells but here I have other issue. I just want to have ImageView on first cell of first section so I have used IndexPath.Section==0 and IndexPath.Row==0 condition in following code but the problem is when I scroll table, the other cell will meet this condition and my code will create imageview on that cell as well. I have tried Tagging it and using same tagged cellView but it didn't help either. The cell issue is with disabling user interactions for few cells. Eventually after scrolling it disables user interactions for all cells. Is there anyway to resolve this?
Thanks.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
if(indexPath.section == 0 && indexPath.row == 0) {
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"me.jpg"]] autorelease];
UIView *cellView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0,320,132)] autorelease];
[imageView setFrame: CGRectMake(10, 10, 54, 54)];
[cellView addSubview:imageView];
cell.backgroundView = cellView;
return cell;
} else if(indexPath.row == 0) {
NSString * title = [NSString string];
switch (indexPath.section) {
case 1:
title = #"Friends";
break;
case 2:
title = #"Accounts";
break;
case 3:
title = #"Stats";
break;
default:
title = nil;
break;
}
cell.textLabel.text = title;
cell.userInteractionEnabled = NO;
return cell;
}
cell.textLabel.text = #"Test";
return cell;
}
[RESOLVED] Correct code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
if(indexPath.section == 0 && indexPath.row == 0) {
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"me.jpg"]] autorelease];
cell.imageView.image = imageView.image;
cell.textLabel.text = nil;
cell.textLabel.textColor = [UIColor clearColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.userInteractionEnabled = YES;
return cell;
} else if(indexPath.row == 0) {
NSString * title = [NSString string];
switch (indexPath.section) {
case 1:
title = #"Friends";
break;
case 2:
title = #"Accounts";
break;
case 3:
title = #"Stats";
break;
default:
title = nil;
break;
}
cell.imageView.image = nil;
cell.textLabel.text = title;
cell.textLabel.textColor = [UIColor redColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.userInteractionEnabled = NO;
return cell;
}
cell.imageView.image = nil;
cell.textLabel.text = [cellItems objectAtIndex:(rows+indexPath.row-1)];
cell.textLabel.textColor = [UIColor blueColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.userInteractionEnabled = YES;
return cell;
}
[IMPROVED CODE]
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *NormalCellIdentifier = #"NormalCell";
static NSString *TitleCellIdentifier = #"TitleCell";
NSString *neededCellType;
if(indexPath.section == 0 && indexPath.row == 0) {
neededCellType = TitleCellIdentifier;
} else {
neededCellType = NormalCellIdentifier;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:neededCellType];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:neededCellType] autorelease];
//Only add content to cell if it is new
if([neededCellType isEqualToString: TitleCellIdentifier]) {
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"me.jpg"]] autorelease];
cell.imageView.image = imageView.image;
}
}
if([neededCellType isEqualToString: NormalCellIdentifier]) {
NSString * title;
if(indexPath.row == 0) {
switch (indexPath.section) {
case 1:
title = #"Friends";
break;
case 2:
title = #"Accounts";
break;
case 3:
title = #"Stats";
break;
default:
title = nil;
break;
}
cell.textLabel.text = title;
cell.textLabel.textColor = [UIColor redColor];
cell.userInteractionEnabled = NO;
} else {
cell.userInteractionEnabled = YES;
cell.textLabel.textColor = [UIColor blueColor];
cell.textLabel.text = #"Test";
}
}
return cell;
}
I think your problem is that the reuse of cells makes it so that the cells that aren't being created as new cells have some properties set that you must redefine. For instance, try assigning cell.userInteractionEnabled = YES to all other cases and see what the result is.
The problem is that you are not allowing for the possibility that the cell that was correctly showing the image gets reused later and the image view is still in there.
Here are two solutions:
set the tag value of the image view when you create it, then when you setup the cells, include code to check for and remove the old imageView if necessary.
assign different reuse identifiers to cells that need an image view and those that do not. Then make sure that you are only adding a new image view to cells when they are being created and not when they are being reused.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *NormalCellIdentifier = #"NormalCell";
static NSString *TitleCellIdentifier = #"TitleCell";
NSString *neededCellType;
if(indexPath.section == 0 && indexPath.row == 0) {
neededCellType = TitleCellIdentifier;
} else {
neededCellType = NormalCellIdentifier;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:neededCellType];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:neededCellType] autorelease];
//Only add content to cell if it is new
if([neededCellType isEqualToString: TitleCellIdentifier]) {
UIImageView *imageView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"me.jpg"]] autorelease];
UIView *cellView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0,320,132)] autorelease];
[imageView setFrame: CGRectMake(10, 10, 54, 54)];
[cellView addSubview:imageView];
cell.backgroundView = cellView;
}
}
if([neededCellType isEqualToString: NormalCellIdentifier]) {
NSString * title;
if(indexPath.row == 0) {
switch (indexPath.section) {
case 1:
title = #"Friends";
break;
case 2:
title = #"Accounts";
break;
case 3:
title = #"Stats";
break;
default:
title = nil;
break;
}
cell.textLabel.text = title;
cell.userInteractionEnabled = NO;
}
else {
cell.textLabel.text = #"Test";
return cell;
}
}
}
(Those last few lines fell out of the code box). That should do it.
i am working on an iphone project that shows an artwork at the top tableview section (section 0) and shows a list of items in (section 1). the tableview looks like that:
section0:
ARTWORK IMAGE
section1:
cell1: text1
cell2: text2
.
.
. and so goe like that.
but strangely the program shows another imageview at the bottom of the page when i scroll down, but it shouldnt show that image because its not section 0.
heres the code for my program :
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
switch (section) {
case 0:
return 1;
break;
case 1:
return [diskArray count];
break;
default:
return 0;
break;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case 0:
return 225;
break;
default:
return 44;
break;
}
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
if(indexPath.section == 0)
{
if(indexPath.row == 0)
{
NSLog(#"adding image to the cell");
UIImage *img = [UIImage imageNamed:#"artwork.jpeg"];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(47, 0, 225, 225)];
imgView.image = img;
[cell addSubview:imgView];
[imgView release];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.text = nil;
}
}
else if(indexPath.section == 1){
cell.textLabel.text = [diskArray objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor darkGrayColor];
cell.textLabel.textColor = [UIColor whiteColor];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
The iPhone reuses old cells with the subview you've added. Try changing the CellIdentifier for each section.
It's because you reuse the cell, but nowhere it is reinitialized.
try this to remove the image :
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
} else {
[cell subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
//you should also reinit the other values, as textLabel, bgColor et al.
}