Programmatically created UITableViewCell subclass only working on highlight - iphone

I've created a subclass of UITableViewCell but I'm struggling to get it to work properly. If I use UITableViewStyleDefault then the class only works when highlighted. If I use UITableViewStyleValue1 then it mostly works but I'm unable to change label fonts much.
I tried researching but it seems everyone is doing this via a .xib file, but not programmatically.
Implementation file
#import "ASCustomCellWithCount.h"
#implementation ASCustomCellWithCount
#synthesize primaryLabel,secondaryLabel,contentCountImage,contentCount;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
contentCountImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed: #"tableCount.png"] ];
primaryLabel = [[UILabel alloc] init];
primaryLabel.textAlignment = UITextAlignmentLeft;
primaryLabel.textColor = [UIColor blackColor];
primaryLabel.font = [UIFont systemFontOfSize: 20];
primaryLabel.backgroundColor = [UIColor clearColor];
secondaryLabel = [[UILabel alloc] init];
secondaryLabel.textAlignment = UITextAlignmentLeft;
secondaryLabel.textColor = [UIColor blackColor];
secondaryLabel.font = [UIFont systemFontOfSize: 8];
secondaryLabel.backgroundColor = [UIColor clearColor];
contentCount = [[UILabel alloc] init];
contentCount.textAlignment = UITextAlignmentCenter;
contentCount.font = [UIFont boldSystemFontOfSize: 15];
contentCount.textColor = [UIColor whiteColor];
contentCount.shadowColor = [UIColor blackColor];
contentCount.shadowOffset = CGSizeMake(1, 1);
contentCount.backgroundColor = [UIColor clearColor];
[self.contentView addSubview: contentCountImage];
[self.contentView addSubview: primaryLabel];
[self.contentView addSubview: secondaryLabel];
[self.contentView addSubview: contentCount];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
// CGFloat boundsX = contentRect.origin.x;
primaryLabel.frame = CGRectMake(0 ,0, 200, 25);
secondaryLabel.frame = CGRectMake(0, 30, 100, 15);
contentCount.frame = CGRectMake(contentRect.size.width - 48, contentRect.size.height / 2 - 13, 36, 24);
contentCountImage.frame = CGRectMake(contentRect.size.width - 48, contentRect.size.height / 2 - 12, 36, 24);
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc {
[primaryLabel release];
[secondaryLabel release];
[contentCountImage release];
[contentCount release];
}
#end
And then to create the cell I use
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
ASCustomCellWithCount *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[ASCustomCellWithCount alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#", [tempArray objectAtIndex: indexPath.row]];
cell.contentCount.text = #"49";
return cell;
}

For the sake of completeness, my issue was trying to use the custom cells default cell.textLabel.text rather than my custom cell.primaryLabel.text.
As soon as you use one of the default objects in a cell it reverts to the default cells rather than a subclass.

Related

Custom UITableViewCell is empty, although cell from heightForRowAtIndexPath is correct

Sorry, I am missing it. I have a beautiful table with correct (variable) row heights. But all the cells are blank. Three labels should be populated in each cell.
UPDATE: FIX IS BELOW
#implementation MasterTableCell
#synthesize labelDesc;
#synthesize labelDuration;
#synthesize labelName;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// name
CGRect frameTextLabel = CGRectMake(8, 2, 244, 25);
labelName = [[UILabel alloc] initWithFrame:frameTextLabel];
labelName.lineBreakMode = UILineBreakModeTailTruncation;
labelName.font = [UIFont boldSystemFontOfSize:17.0];
labelName.textColor = [UIColor blackColor];
// description
labelDesc = [[UILabel alloc] init];
labelDesc.lineBreakMode = UILineBreakModeWordWrap;
labelDesc.numberOfLines = 0;
labelDesc.textColor = [UIColor grayColor];
labelDesc.font = [UIFont systemFontOfSize:14.0f];
labelDesc.backgroundColor = [UIColor blueColor];
// duration
CGRect frame = CGRectMake(252, 5, 40, 20);
labelDuration = [[UILabel alloc] initWithFrame:frame];
labelDuration.font = [UIFont boldSystemFontOfSize:14.f ];
labelDuration.textAlignment = UITextAlignmentRight;
labelDuration.backgroundColor = [UIColor redColor]; // to see it
[self.contentView addSubview:labelName];
[self.contentView addSubview:labelDesc];
[self.contentView addSubview:labelDuration];
}
return self;
}
#end
And
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"RecipeCell";
MasterTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[MasterTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Recipe *recipeAtIndex = [sortedArray objectAtIndex:indexPath.row];
cell.labelName.text = #"Test1";
cell.labelDesc.text = #"Test2";
cell.labelDuration.text = [TBCommon formattedStringforDuration:recipeAtIndex.duration withDelimeter:#":"];
CGRect frameDescLabel = CGRectMake(8, 25, 284, [self heightForDescriptionFrame:recipeAtIndex.description]);
cell.labelDesc.frame = frameDescLabel;
return cell;
}
FIX
#import "MasterTableCell.h"
#implementation MasterTableCell : UITableViewCell
#synthesize labelDesc;
#synthesize labelDuration;
#synthesize labelName;
- (void)awakeFromNib
{
[super awakeFromNib];
// name
CGRect frameTextLabel = CGRectMake(8, 2, 244, 25);
labelName = [[UILabel alloc] initWithFrame:frameTextLabel];
labelName.lineBreakMode = UILineBreakModeTailTruncation;
labelName.font = [UIFont boldSystemFontOfSize:17.0];
labelName.textColor = [UIColor blackColor];
// description
labelDesc = [[UILabel alloc] init];
labelDesc.lineBreakMode = UILineBreakModeWordWrap;
labelDesc.numberOfLines = 0;
labelDesc.textColor = [UIColor grayColor];
labelDesc.font = [UIFont systemFontOfSize:14.0f];
// duration
CGRect frame = CGRectMake(252, 5, 40, 20);
labelDuration = [[UILabel alloc] initWithFrame:frame];
labelDuration.textColor = [UIColor colorWithRed:38.0/255.0 green:111.0/255.0 blue:208.0/255.0 alpha:1];
labelDuration.font = [UIFont boldSystemFontOfSize:14.f ];
labelDuration.textAlignment = UITextAlignmentRight;
[self.contentView addSubview:labelName];
[self.contentView addSubview:labelDesc];
[self.contentView addSubview:labelDuration];
}
#end
And
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
MasterTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Recipe *recipeAtIndex = [sortedArray objectAtIndex:indexPath.row];
cell.labelName.text = recipeAtIndex.name;
cell.labelDesc.text = recipeAtIndex.description;
cell.labelDuration.text = [TBCommon formattedStringforDuration:recipeAtIndex.duration withDelimeter:#":"];
CGRect frameDescLabel = CGRectMake(8, 25, 284, [self heightForDescriptionFrame:recipeAtIndex.description]);
cell.labelDesc.frame = frameDescLabel;
return cell;
}
If you're using Storyboards, initWithStyle will never be called. Move the label creation code into awakeFromNib.
You can get rid of the whole if (cell == nil) part too because dequeueReusableCell will ALWAYS return a cell.
Do you think that your table view delegate/datasource method are actually being called. Trying putting a break point in cellForRowAtIndexPath method to verify that. If breakpoint's not hit it means your delegate and datasource are not set. Set those.
Another thing that I noticed is that you have not set the frame for your labelDesc instance variable. That's worth looking at.
When I was setting up my custom cell subclasses, the tutorial I was following had me set the frames in a separate method called layoutSubviews. For you, it would look like
- (void) layoutSubviews
{
[super layoutSubviews];
labelName.frame = CGRectMake(8, 2, 244, 25);
labelDuration.frame = CGRectMake(252, 5, 40, 20);
}
When I had something to add to a cell that is dynamically located like labelDesc is, I had to totally pull it out of my custom cells class and put it all in cellForRowAtIndexPath (so I would have something like labelDesc = [[UILabel alloc] initWithFrame... and so on all in cellForRowAtIndexPath, and nothing for it in the initWithStyle).
I don't know why doing it this way is any different than setting the frames in initWithStyle, but it seems to be working for me.

adding subviews to cell view showing strange behavior

I m trying to add cells to a tableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
cell.accessoryType = UITableViewCellAccessoryNone;
[cell setSelectionStyle:UITableViewCellEditingStyleNone];
// Set up the cell
cell.backgroundColor = [UIColor clearColor];
UIButton *buyBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImageView *img;
UILabel *lbl;
UIImageView *backImage;
UILabel *textLabel;
UILabel *detailTextLabel;
NSInteger val = [indexPath row] * 3;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
//*buyBtn = [[UIButton alloc] initWithFrame:CGRectMake(x, y, w, h)];
[buyBtn setImage:[UIImage imageNamed:#""] forState:UIControlStateNormal];
//*img = [[UIImageView alloc] initWithFrame:CGRectMake(x, y, w, h)];
[img setImage:[UIImage imageNamed:#""]];
//*lbl = [[UILabel alloc] initWithFrame:CGRectMake(x,y,w,h)];
}
else
{
backImage = [[UIImageView alloc] initWithFrame:CGRectMake(2, 4, 316, 62)];
[buyBtn setFrame:CGRectMake(257, 100, 57, 24)];
img = [[UIImageView alloc] initWithFrame:CGRectMake(257, 75, 57, 24)];
lbl = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 57, 24)];
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(4, 4, 230, 25)];
detailTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(4, 25, 230, 30)];
backImage.image = [UIImage imageNamed:#"shop-bg.png"];
[buyBtn setImage:[UIImage imageNamed:#"buy_button"] forState:UIControlStateNormal];
[img setImage:[UIImage imageNamed:#"price_button.png"]];
lbl.center = img.center;
lbl.textAlignment = UITextAlignmentCenter;
lbl.text = [self.original_List objectAtIndex:val+2];
lbl.backgroundColor = [UIColor clearColor];
textLabel.font = [UIFont fontWithName:#"Arial Rounded MT Bold" size:14];
textLabel.backgroundColor = [UIColor clearColor];
textLabel.text = [self.original_List objectAtIndex:val];
detailTextLabel.text = [self.original_List objectAtIndex:val+1];
detailTextLabel.backgroundColor = [UIColor clearColor];
detailTextLabel.font = [UIFont fontWithName:#"Arial Rounded MT Bold" size:10];
textLabel.textColor = [UIColor blackColor];
detailTextLabel.textColor = [UIColor whiteColor];
detailTextLabel.numberOfLines = 2;
}
[buyBtn setTag:[indexPath row]];
[buyBtn addTarget:self action:#selector(buyBtnPressed:) forControlEvents:UIControlEventTouchDown];
[cell addSubview:backImage];
[cell addSubview:detailTextLabel];
[cell addSubview:textLabel];
[cell addSubview:buyBtn];
[cell addSubview:img];
[cell addSubview:lbl];
return cell;
}
From figure it can be seen that The first Cell DOES NOT Contain the added image, label and button, however if other cells are scrolled those who lost view turn transparent while those who are in view are okay.
Why is my three subview not getting added from first cell, my textLabel and detailTextLabel are added as they should.
First of all you don't dequeue the cell and always create a new one without reusing. Try adding something like this (not sure if you need autorelease, depends on weather you use ARC or not):
RecentsTableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[RecentsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier] autorelease];
}
Second, if you are not using ARC (auto ref counting) then you have bunch of lost refs here.
[[Class alloc] init] adds the ref and addSubview also adds the ref. I'm wondering what xcode "analyse" build says on this.
Third, imho all labels you added to the cell need also their "frame" property to set up, not just number of lines, etc.
here is example of how I did it. I created cell class derived what what you need (CopyableCell in my case).
This is *.h file.
#import <UIKit/UIKit.h>
#import "CopyableCell.h"
#interface RecentsTableViewCell : CopyableCell
#property (readonly, retain) UILabel *titleLabel;
#property (readonly, retain) UILabel *detailsLabel;
#property (readonly, retain) UILabel *subdetailsLabel;
#property (readonly, retain) UILabel *subtitleLabel;
#end
Here is *.m file.
#import "RecentsTableViewCell.h"
#interface RecentsTableViewCell ()
// Redeclare property as readwrite
#property (readwrite, retain) UILabel *titleLabel;
#property (readwrite, retain) UILabel *subtitleLabel;
#property (readwrite, retain) UILabel *detailsLabel;
#property (readwrite, retain) UILabel *subdetailsLabel;
#end
#implementation RecentsTableViewCell
#synthesize titleLabel;
#synthesize subtitleLabel;
#synthesize detailsLabel;
#synthesize subdetailsLabel;
- (void) layoutSubviews
{
int leftMargin = 30;
int rightMargin = 6;
[super layoutSubviews];
CGRect cellRect = self.contentView.frame;
int width = cellRect.size.width - (leftMargin + rightMargin);
CGSize constraintSize = CGSizeMake(300, MAXFLOAT);
CGSize titleSize = [titleLabel.text sizeWithFont:titleLabel.font
constrainedToSize:constraintSize
lineBreakMode:UILineBreakModeTailTruncation];
CGSize detailsSize = [detailsLabel.text sizeWithFont:detailsLabel.font
constrainedToSize:constraintSize
lineBreakMode:UILineBreakModeTailTruncation];
if (titleSize.width > titleLabel.frame.size.width ||
detailsSize.width > detailsLabel.frame.size.width) {
CGRect detailsFrame = detailsLabel.frame;
detailsFrame.size.width = detailsSize.width;
detailsFrame.origin.x = cellRect.size.width -
(detailsSize.width + subdetailsLabel.frame.size.width + rightMargin);
CGRect titleFrame = titleLabel.frame;
titleFrame.size.width = width - detailsSize.width - subdetailsLabel.frame.size.width - 5;
titleLabel.frame = titleFrame;
detailsLabel.frame = detailsFrame;
}
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
CGRect cellRect = self.contentView.frame;
cellRect.size.height = 61;
self.contentView.frame = cellRect;
int leftMargin = 30;
int rightMargin = 6;
int x = cellRect.origin.x + leftMargin;
int y = cellRect.origin.y;
int width = cellRect.size.width - (leftMargin + rightMargin);
int height = cellRect.size.height;
int titleWidth = width * 0.75;
int alldetailsWidth = width - titleWidth;
int detailsWidth = alldetailsWidth * 0.65;
int subdetailsWidth = alldetailsWidth - detailsWidth;
int titleHeight = height * 0.38;
int subtitleHeight = height - titleHeight;
self.titleLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(x, y, titleWidth, titleHeight)] autorelease];
self.titleLabel.font = [UIFont boldSystemFontOfSize:18.0f];
self.titleLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.titleLabel.textAlignment = UITextAlignmentLeft;
self.titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleBottomMargin;
[self.contentView addSubview:titleLabel];
self.detailsLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(cellRect.size.width -
(detailsWidth + subdetailsWidth + rightMargin),
y + 4, detailsWidth, titleHeight - 4)] autorelease];
self.detailsLabel.font = [UIFont boldSystemFontOfSize:13.0f];
self.detailsLabel.textColor = [UIColor colorWithRed:0.12 green:0.439 blue:0.847 alpha:1];
self.detailsLabel.textAlignment = UITextAlignmentRight;
self.detailsLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.detailsLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:detailsLabel];
self.subdetailsLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(cellRect.size.width - (subdetailsWidth + rightMargin),
y + 6, subdetailsWidth, titleHeight - 6)] autorelease];
self.subdetailsLabel.font = [UIFont systemFontOfSize:11.0f];
self.subdetailsLabel.textColor = [UIColor colorWithRed:0.12 green:0.439 blue:0.847 alpha:1];
self.subdetailsLabel.textAlignment = UITextAlignmentCenter;
self.subdetailsLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.subdetailsLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleHeight;
[self.contentView addSubview:subdetailsLabel];
self.subtitleLabel = [[[UILabel alloc]
initWithFrame:CGRectMake(x, y + titleHeight, width, subtitleHeight - 2)] autorelease];
self.subtitleLabel.highlightedTextColor = self.textLabel.highlightedTextColor;
self.subtitleLabel.font = [UIFont systemFontOfSize:13.0f];
self.subtitleLabel.textColor = [UIColor darkGrayColor];
self.subtitleLabel.numberOfLines = 2;
self.subtitleLabel.lineBreakMode = UILineBreakModeTailTruncation;
self.subtitleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleTopMargin;
[self.contentView addSubview:subtitleLabel];
self.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return self;
}
- (id) init
{
return [self initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"RecentsCell"];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
}
- (void) dealloc
{
self.titleLabel = nil;
self.subtitleLabel = nil;
self.detailsLabel = nil;
self.subdetailsLabel = nil;
[super dealloc];
}
#end
Note that I'm not using ARC so if you use this code, modify it accordingly. Here is how I use this class in my table view controller.
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"TransactionCell";
NSMutableArray *data = searching ? searchResult : dataSource;
NSDictionary *object = [data objectAtIndex:[indexPath row]];
RecentsTableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[RecentsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.indexPath = indexPath;
cell.delegate = self;
cell.titleLabel.text = #"Transaction title";
if (pendingTransaction) {
cell.titleLabel.textColor = [UIColor grayColor];
cell.titleLabel.font = [UIFont systemFontOfSize:cell.titleLabel.font.pointSize];
} else {
if (!isGreen)
cell.titleLabel.textColor = [UIColor colorWithRed:0.733 green:0.098
blue:0.098 alpha:1];
else
cell.titleLabel.textColor = cell.textLabel.textColor;
cell.titleLabel.font = [UIFont boldSystemFontOfSize:cell.titleLabel.font.pointSize];
}
cell.subtitleLabel.text = #"Transaction subtitle";
cell.detailsLabel.text = #"Some details like location";
cell.subdetailsLabel.text = #"200 USD";
return cell;
}
This produces table very similar to what you see in iphone call app, that is, title, subtitle, subdetails in blue at rightmost position of the cell, etc.
You can see it in Torchoo app in the appstore. It is free to use and you can use test account to log in and see it as example.
Hope this helps a bit.
Are you continuously adding subView to cell not removing any subView?
Check condition while adding subView like code not exact I have written:
if ([[cell.contentView subviews] count]==0) {
[self.contentView addSubview:imageView];
}
If cell content View doesn't contain that View then add it.
Previous answer is correct although there is more that you could fix.
The part of code that adds subviews should only be called in case when the cell is not dequeued. Otherwise you'll be adding multiple instances of the same buttons, views etc.
[cell addSubview:backImage];
[cell addSubview:detailTextLabel];
[cell addSubview:textLabel];
[cell addSubview:buyBtn];
[cell addSubview:img];
[cell addSubview:lbl];
Also I guess it is better to add to cell.contentView instead of directly to cell. So it should look something like this:
RecentsTableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[RecentsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:cellIdentifier] autorelease];
/*Create your subviews here*/
[cell.contentView addSubview:backImage];
[cell.contentView addSubview:detailTextLabel];
[cell.contentView addSubview:textLabel];
[cell.contentView addSubview:buyBtn];
[cell.contentView addSubview:img];
[cell.contentView addSubview:lbl];
}
// Below just set properties of existing subviews of the cell: color, textColor, text etc.
// You need to retrieve them and one way is to assign them to properties in
// RecentsTableViewCell or set the tag property of the subviews and retrieve
// them using e.g. [cell.contentView viewWithTag:kBuyButtonTag].
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
...
}
else {
...
}

UITableView with performance issues

I make an UITableview (with IB) in my application with 3 types of cell. All works fine except when i drag my tableview all become very slow. So if someone can help me to improve the performance of my app it'll be cool.
My Code for the tableview :
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[myData objectForKey:#"listnews"] count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
return 154;
}
if (indexPath.row == 1) {
return 34;
}
else return 70;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[myTextField resignFirstResponder];
ListNewsCell *cCell = (ListNewsCell *)[myTable dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"cCellIdentifier%d",indexPath.row]];
cCell = [[ListNewsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:#"cCellIdentifier%d",indexPath.row]];
if (indexPath.row == 0) {
NSString * caroline = [[[myData objectForKey:#"listnews"] objectAtIndex:indexPath.row] objectForKey:#"urlimage"];
cCell.c1Image1.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",caroline]]]];
cCell.c1Image2.image = [UIImage imageNamed:#"barreNoireHub.png"];
NSString * sophie = [[[myData objectForKey:#"listnews"] objectAtIndex:indexPath.row] objectForKey:#"titre"];
NSString *itemTitle = sophie ? [sophie stringByConvertingHTMLToPlainText] : #"[No Title]";
cCell.c1Label1.text = itemTitle;
NSString * sonia = [[[myData objectForKey:#"listnews"] objectAtIndex:indexPath.row] objectForKey:#"extrait"];
NSString *itemExtrait = sonia ? [sonia stringByConvertingHTMLToPlainText] : #"[No Title]";
cCell.c1Label2.text = itemExtrait;
}
if (indexPath.row == 1) {
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 34)];
imageView.backgroundColor = [UIColor whiteColor];
imageView.image = [UIImage imageNamed:#"barreSearchHub.png"];
[cCell addSubview:imageView];
[imageView release];
UIView * insertView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 34)];
myTextField = [[UITextField alloc] initWithFrame:CGRectMake(15, 6, 270, 25)];
myTextField.placeholder = #"Recherche";
myTextField.tag = 1;
myTextField.delegate = self;
myTextField.returnKeyType = UIReturnKeySearch;
[insertView addSubview:myTextField];
cCell.accessoryView = insertView;
}
if (indexPath.row > 1) {
cCell.c2Image1.image = [UIImage imageNamed:#"cellM.png"];
NSString * caroline = [[[myData objectForKey:#"listnews"] objectAtIndex:indexPath.row] objectForKey:#"urlimage"];
cCell.c2Image2.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",caroline]]]];
NSString * sophie = [[[myData objectForKey:#"listnews"] objectAtIndex:indexPath.row] objectForKey:#"titre"];
NSString *itemTitle = sophie ? [sophie stringByConvertingHTMLToPlainText] : #"[No Title]";
cCell.c2Label1.text = itemTitle;
NSString * sonia = [[[myData objectForKey:#"listnews"] objectAtIndex:indexPath.row] objectForKey:#"extrait"];
NSString *itemExtrait = sonia ? [sonia stringByConvertingHTMLToPlainText] : #"[No Title]";
cCell.c2Label2.text = itemExtrait;
}
return cCell;
}
The code of the UITableViewCell:
#import "ListNewsCell.h"
#implementation ListNewsCell
#synthesize c1Image1, c1Image2, c1Label1, c1Label2;
#synthesize c2Image1, c2Image2, c2Label1, c2Label2;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
c1Image1 = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,154)];
c1Image1.backgroundColor = [UIColor clearColor];
[self addSubview:c1Image1];
[c1Image1 release];
c1Image2 = [[UIImageView alloc] initWithFrame:CGRectMake(0,98,320,56)];
c1Image2.backgroundColor = [UIColor clearColor];
[self addSubview:c1Image2];
[c1Image2 release];
c1Label1 = [[UILabel alloc] initWithFrame:CGRectMake(5, 100, 310, 20)];
c1Label1.font = [UIFont fontWithName:#"Arial-BoldMT" size:14];
c1Label1.textColor = [UIColor whiteColor];
c1Label1.backgroundColor = [UIColor clearColor];
[self addSubview:c1Label1];
c1Label2 = [[UILabel alloc] initWithFrame:CGRectMake(5, 112, 310, 45)];
c1Label2.font = [UIFont fontWithName:#"Arial" size:12];
c1Label2.textColor = [UIColor whiteColor];
c1Label2.numberOfLines = 2;
c1Label2.backgroundColor = [UIColor clearColor];
[self addSubview:c1Label2];
c2Image1 = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,70)];
c2Image1.backgroundColor = [UIColor clearColor];
[self addSubview:c2Image1];
[c2Image1 release];
c2Label1 = [[UILabel alloc] initWithFrame:CGRectMake(105, 8, 180, 20)];
c2Label1.font = [UIFont fontWithName:#"Arial-BoldMT" size:14];
c2Label1.textColor = [UIColor blackColor];
c2Label1.backgroundColor = [UIColor clearColor];
[self addSubview:c2Label1];
c2Label2 = [[UILabel alloc] initWithFrame:CGRectMake(105, 25, 180, 45)];
c2Label2.font = [UIFont fontWithName:#"Arial" size:12];
c2Label2.textColor = [UIColor blackColor];
c2Label2.numberOfLines = 2;
c2Label2.backgroundColor = [UIColor clearColor];
[self addSubview:c2Label2];
c2Image2 = [[UIImageView alloc] initWithFrame:CGRectMake(20,10,75,55)];
c2Image2.backgroundColor = [UIColor clearColor];
[self addSubview:c2Image2];
[c2Image2 release];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
}
- (void)dealloc
{
[super dealloc];
}
#end
Thanks to all !
The following line causes the big delay:
cCell.c2Image2.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",caroline]]]];
Everytime one of these cells will be loaded, it will make a URL Request. Try to preload a bunch of the data instead of requesting it per cell.
Load the image once, make it a class variable, then just reuse its pointer like:
cCell.c2Image2.image = preloadedImage;
Declare in your .h file:
UIImage * preloadedImage;
And in the - (void) loadView -method put:
preloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",caroline]]]];
Also mind that as jrturton wrote, you want to reuse your dequeued cells for the extra performance boost.
You are never reusing your dequeued cells, so you are recreating everything from scratch every time. Since you have a unique cell for each row (is this really necessary for cells in row 2 and above?) you only need to create and populate them once.
So, you could wrap everything after dequeueReusableCellWithIdentifier onwards inside if (cCell == nil) (the return statement excepted, obviously).
In cellForRowAtIndexPath method you have dequeued some cells from the table view. But you have never used that value. That caused the problem of loading every time rather than re-using.
Try the following code in which I've modified a little..
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[myTextField resignFirstResponder];
ListNewsCell *cCell = (ListNewsCell *)[myTable dequeueReusableCellWithIdentifier:[NSString stringWithFormat:#"cCellIdentifier%d",indexPath.row]];
if(cCell == nil)
{
cCell = [[ListNewsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[NSString stringWithFormat:#"cCellIdentifier%d",indexPath.row]];
}
if (indexPath.row == 0) {
// Some code here
}
if (indexPath.row == 1) {
//Some code here
}
if (indexPath.row > 1) {
// some code here
}
return cCell;
}
Thanks,
Arun.

Custom uitableview cell issue

I have a custom UITableViewCell as such:
#implementation CellWithThreeSubtitles
#synthesize title, subTitle1, subTitle2, subTitle3;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.textLabel.backgroundColor = self.backgroundColor;
self.textLabel.opaque = NO;
self.textLabel.textColor = [UIColor blackColor];
self.textLabel.highlightedTextColor = [UIColor whiteColor];
self.textLabel.font = [UIFont boldSystemFontOfSize:22.0];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGRect frame = CGRectMake(35.0, 0, contentRect.size.width, 50.0);
self.textLabel.frame = frame;
UILabel *subLabel1 = [[UILabel alloc] init];
frame = CGRectMake(35.0, 34.0, contentRect.size.width, 25.0);
subLabel1.font = [UIFont systemFontOfSize:18.0];
subLabel1.backgroundColor = [UIColor clearColor];
subLabel1.text = subTitle1;
subLabel1.opaque = NO;
subLabel1.frame = frame;
[self.contentView addSubview:subLabel1];
UILabel *subLabel2 = [[UILabel alloc] init];
frame = CGRectMake(35.0, 54.0, contentRect.size.width, 25.0);
subLabel2.font = [UIFont boldSystemFontOfSize:18.0];
subLabel2.backgroundColor = [UIColor clearColor];
subLabel2.text = subTitle2;
subLabel2.opaque = NO;
subLabel2.frame = frame;
[self.contentView addSubview:subLabel2];
UILabel *subLabel3 = [[UILabel alloc] init];
frame = CGRectMake(contentRect.size.width-100.0, 54.0, contentRect.size.width, 25.0);
subLabel3.font = [UIFont systemFontOfSize:18.0];
subLabel3.backgroundColor = [UIColor clearColor];
subLabel3.text = subTitle3;
subLabel3.opaque = NO;
subLabel3.frame = frame;
[self.contentView addSubview:subLabel3];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc {
[super dealloc];
[subTitle4 release];
[subTitle3 release];
[subTitle2 release];
[subTitle1 release];
[title release];
}
When I implement it in my UITableView like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
int section = [indexPath indexAtPosition:0];
static NSString *kCustomCellID = #"AppointmentCellID";
CellWithThreeSubtitles *cell = (CellWithThreeSubtitles *)[tableView dequeueReusableCellWithIdentifier:kCustomCellID];
if (cell == nil) {
cell = (CellWithThreeSubtitles *)[[[CellWithThreeSubtitles alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCustomCellID] autorelease];
}
switch (section) {
case 0:
if ([wineArray count]==0) {
cell.textLabel.text = #"No wine favorites selected yet";
}else{
cell.subTitle1 = [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Varietal"];
cell.subTitle2 = [NSString stringWithFormat:#"Bin No. %#", [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Bin"]];
cell.subTitle3 = [NSString stringWithFormat:#"$%#", [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Price"]];
cell.textLabel.text = [NSString stringWithFormat:#"%# (%#)", [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Name"], [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Availability"]];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.userInteractionEnabled = NO;
break;
case 1:
if ([dinnerArray count]==0)
cell.textLabel.text = #"No dinner favorites selected yet";
else
cell.textLabel.text = [NSString stringWithFormat:#"%#", [[dinnerArray objectAtIndex:indexPath.row] objectForKey:#"Name"]];
break;
}
return cell;
}
the contents of the cell duplicates on top of itself every time the orientation of the device changes. Is it redrawing the cell every time the device rotates? And if so, How can I keep it from doing so?
You should be creating the subviews and adding them to your cell's subviews array in your -initWithStyle:reuseIdentifier: method. You only need to create the subviews once. The -layoutSubviews method is invoked repeatedly by the framework whenever the device orientation changes, to allow you to resize and/or move the subviews (plus make any other minor adjustments) to compensate for differences between the orientations.
I suspect layoutSubViews is being called on rotation, and re-drawing new labels on top of your old ones. If you remove any labels from the table cell at the beginning of layoutSubViews that would probably fix that issue, or you could create them in the init and then just position them in layoutSubViews.

UITableViewCell repeats after scrolling

I am not sure why my UITableViewCell's are repeating after the user scrolls?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
ChartlyCell *cell = (ChartlyCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//cell = [[[ChartlyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell = [[[ChartlyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier andDelegate:self] autorelease];
}
ChartlyObject *myChartlyObject;
myChartlyObject = [self.items objectAtIndex:indexPath.row];
cell.usernameLabel.text = myChartlyObject.userName;
cell.bodyLabel.text = myChartlyObject.chart_message;
[cell.messageLabel setText: myChartlyObject.chart_message];
cell.timeLabel.text = [Utils toShortTimeIntervalStringFromStockTwits: myChartlyObject.created_at];
[cell.chartImage loadImageFromURL:[NSURL URLWithString:myChartlyObject.imageThumbnail]];
return cell;
}
This is how the cell is being created:
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier andDelegate:(id<NLabelDelegate>)ndelegate{
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
// Initialization code
CGRect rect;
rect = CGRectMake(77, 5, 200, 20); //CGRectMake(10, 5, 200, 20);
usernameLabel = [[UILabel alloc] initWithFrame:rect];
//usernameLabel.backgroundColor = backgroundColor;
usernameLabel.font = [Utils getBoldSystemFontWithSize:14];
usernameLabel.textColor = [UIColor colorWithRed:.368 green:.741 blue:.784 alpha:1];
[self.contentView addSubview: usernameLabel];
rect = CGRectMake(277, 5, 38, 20);
timeLabel = [[UILabel alloc] initWithFrame:rect];
timeLabel.textAlignment = UITextAlignmentRight;
//timeLabel.backgroundColor = backgroundColor;
timeLabel.font = [Utils getBoldSystemFontWithSize:14];
timeLabel.textColor = [UIColor colorWithRed:.98 green:.65 blue:.01 alpha:1];
[self.contentView addSubview: timeLabel];
/*rect = CGRectMake(77, 25, 238, 68); //CGRectMake(10, 50, 238, 68);
bodyLabel = [[UILabel alloc] initWithFrame:rect];
bodyLabel.font = [Utils getSystemFontWithSize:10];
bodyLabel.numberOfLines = 3;
bodyLabel.lineBreakMode = UILineBreakModeWordWrap;
bodyLabel.textColor = [UIColor blackColor];
bodyLabel.backgroundColor = [UIColor clearColor];
[self.contentView addSubview: bodyLabel];*/
rect = CGRectMake(77, 25, 238, 68);
messageLabel = [[NLabel alloc] initWithFrame:rect andDelegate:ndelegate];
[messageLabel setOpaque:NO];
[messageLabel setBackgroundColor: [UIColor blackColor]];
//[messageLabel setTotalheight:68];
[self.contentView addSubview: messageLabel];
rect = CGRectMake(13, 10, 48, 48);
chartImage = [[AsyncImageView alloc]initWithFrame:rect];
[self.contentView addSubview: chartImage];
}
return self;
}
UPDATE:
What is odd, is that if I uncomment the bodyLabel block and comment out the messageLabel block the repeating cells don't appear anymore. I am not sure why and would still like to find a resolution
UPDATE #2
Only messageLabel gets repeated. All of the other labels do NOT repeat. Why is this?
Because you are re-using tablecells for proper memory management as you should be doing via dequeueReusableCellWithIdentifier :) This way you don't have a unique cell for every single cell you need. Instead you only have about 5 or 6 that get re-used over and over during scrolling.
When the cell comes back into view, you need to reset the state (i.e. update the info, labels, images, etc) of each cell based on whatever cell came into view.
One thing you can do is to remove all the views in the cell.contentView after you create the cell or dequeue it. Alternatively, you can create a custom cell with attributes for the labels that you can set to different values when you scroll down.