UITableViewCell background repeats if cell scrolls off screen - iphone

I want to apply a special background to the first cell in my UITableView:
I am applying the bg in:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
This is how it is applied:
if (indexPath.row == 1) {
cell.contentView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"top-message-bg.png"]];
}
The problem is, when this cell scrolls off screen, a new cell will have indexPath.row == 1. How can I make sure only this cell has this background?
UPDATE: Here is the full method
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
STVCell *cell = (STVCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (indexPath.row == 0) {
if(mainVideoCell == nil)
{
mainVideoCell = [[MainVideoCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"MainVideoCell"];
mainVideoCell.contentView.backgroundColor = [UIColor colorWithRed:242.0/255.0 green:242.0/255.0 blue:242.0/255.0 alpha:1.0];
}
// Configure the cell...
STVideo *mySTVideo;
mySTVideo = [items objectAtIndex:indexPath.row];
mainVideoCell.videoTitle.text = mySTVideo.video_title;
/*NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSDateFormatterNoStyle];
NSString *result = [formatter stringFromDate:[NSDate date]];
[formatter release];*/
mainVideoCell.dateLabel.text = [Utils toShortTimeIntervalStringFromStockTwits:mySTVideo.publish_on]; //result; //[mySTVideo.publish_on substringToIndex:10];//[Utils toShortTimeIntervalStringFromStockTwits:mySTVideo.publish_on];
mainVideoCell.videoDescription.text = mySTVideo.description;
mainVideoCell.authorLabel.text = [NSString stringWithFormat:#"with %#", mySTVideo.author];
[mainVideoCell.videoThumbnail loadImageFromURL:[NSURL URLWithString:mySTVideo.thumbnail_url]];
NSLog(#"Description:%#",mySTVideo.description);
return mainVideoCell;
}
else {
if (cell == nil) {
//cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
cell = [[[STVCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
STVideo *mySTVideo;
mySTVideo = [items objectAtIndex:indexPath.row];
cell.videoTitle.text = mySTVideo.video_title;
/*NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSDateFormatterNoStyle];
NSString *result = [formatter stringFromDate:[NSDate date]];
[formatter release];*/
cell.dateLabel.text = [Utils toShortTimeIntervalStringFromStockTwits:mySTVideo.publish_on];//result; //[mySTVideo.publish_on substringToIndex:10];//[Utils toShortTimeIntervalStringFromStockTwits:mySTVideo.publish_on];
cell.videoDescription.text = mySTVideo.description;
cell.authorLabel.text = [NSString stringWithFormat:#"with %#", mySTVideo.author];
[cell.videoThumbnail loadImageFromURL:[NSURL URLWithString:mySTVideo.thumbnail_url]];
if (indexPath.row == 1) {
cell.contentView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"top-message-bg.png"]];
}
else {
UIImageView* imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
imageView.image = [[UIImage imageNamed:#"message-bg.png"] stretchableImageWithLeftCapWidth:1 topCapHeight:20];//[[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"message-bg.png"]];
[imageView setOpaque:YES];
[cell setBackgroundView:imageView];
[imageView release];
}
return cell;
}
}

Show us the whole code for cellForRowAtIndexPath please. I suspect that you are simply not configuring the cells correctly. I could be wrong but are you doing this background stuff only when you actually create the cell? Cells are cached so you have to make sure that you set the background to normal for every cell that comes out of the cache.
if (indexPath.row == 1) {
cell.contentView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"top-message-bg.png"]];
}
else
{
cell.contentView.backgroundColor = // whatever normal background is
}

Sounds like there's something wrong with the way you're reusing your cells. The problem is not that the indexPath.row equals one, but that the cell you created for the row=1 cell is being reused. Perhaps you should add an else condition:
if (indexPath.row == 1) {
cell.contentView.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"top-message-bg.png"]];
}
else {
cell.contentView.backgroundColor = [UIColor whiteColor];
}

Related

UITableView Showing 2 Cells For Every Item

My tableview parses a calendar RSS Feed. I set up the cell to have a blank calendar icon as the image for every cell, and add subviews for the month and day, which it detects using NSDate from the RSS itself. However, for some reason, it shows 2 cells for every event, and I cannot figure out why. Here is the code for the cell:
- (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] autorelease];
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM"];
NSString *monthfromdate = [formatter stringFromDate:entry.articleDate];
NSLog(#"%#", monthfromdate);
[formatter release];
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter2 setDateFormat:#"dd"];
NSString *datefromdate = [formatter2 stringFromDate:entry.articleDate];
NSLog(#"%#", datefromdate);
[formatter2 release];
if ([monthfromdate isEqualToString:#"01"]) {
self.currentmonth = #"January";
}
if ([monthfromdate isEqualToString:#"02"]) {
self.currentmonth = #"February";
}
if ([monthfromdate isEqualToString:#"03"]) {
self.currentmonth = #"March";
}
if ([monthfromdate isEqualToString:#"04"]) {
self.currentmonth = #"April";
}
if ([monthfromdate isEqualToString:#"05"]) {
self.currentmonth = #"May";
}
if ([monthfromdate isEqualToString:#"06"]) {
self.currentmonth = #"June";
}
if ([monthfromdate isEqualToString:#"07"]) {
self.currentmonth = #"July";
}
if ([monthfromdate isEqualToString:#"08"]) {
self.currentmonth = #"August";
}
if ([monthfromdate isEqualToString:#"09"]) {
self.currentmonth = #"September";
}
if ([monthfromdate isEqualToString:#"10"]) {
self.currentmonth = #"October";
}
if ([monthfromdate isEqualToString:#"11"]) {
self.currentmonth = #"November";
}
if ([monthfromdate isEqualToString:#"12"]) {
self.currentmonth = #"December";
}
NSString *currentday = datefromdate;
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"ArialRoundedMTBold" size:15];
UIFont *cellFont2 = [UIFont fontWithName:#"ArialRoundedMTBold" size:12];
UIFont *cellFont3 = [UIFont fontWithName:#"ArialRoundedMTBold" size:9];
UIFont *cellFont4 = [UIFont fontWithName:#"ArialRoundedMTBold" size:18];
UILabel *month = [[UILabel alloc] initWithFrame:CGRectMake(8, 10, 53, 21)];
month.font = cellFont3;
month.text = currentmonth;
month.textAlignment = UITextAlignmentCenter;
month.backgroundColor = [UIColor clearColor];
UILabel *date = [[UILabel alloc] initWithFrame:CGRectMake(11, 21, 50, 45)];
date.font = cellFont4;
date.text = currentday;
date.textAlignment = UITextAlignmentCenter;
date.backgroundColor = [UIColor clearColor];
UIImageView *alternate = [[UIImageView alloc] initWithFrame:CGRectMake(1,1,69,69)];
alternate.image = [UIImage imageNamed:#"calendar1.png"];
alternate.contentMode = UIViewContentModeScaleAspectFit;
UILabel *alternatelabel = [[UILabel alloc] initWithFrame:CGRectMake(82,0,228,53)];
alternatelabel.backgroundColor = [UIColor clearColor];
CALayer * l = [alternate layer];
[l setMasksToBounds:YES];
UILabel *detailLabel = [[UILabel alloc] initWithFrame:CGRectMake(82, 20, 228, 53)];
detailLabel.backgroundColor = [UIColor clearColor];
detailLabel.text = [NSString stringWithFormat:#"%# - %#", articleDateString, entry.blogTitle];
detailLabel.textColor = [UIColor grayColor];
detailLabel.font = cellFont2;
alternatelabel.font = cellFont;
alternatelabel.text = entry.articleTitle;
[cell.contentView addSubview:alternate];
[cell.contentView addSubview:alternatelabel];
[cell.contentView addSubview:detailLabel];
[cell.contentView addSubview:month];
[cell.contentView addSubview:date];
[detailLabel release];
[alternatelabel release];
[alternate release];
}
return cell;
}
You are wrong using cell reusing mechanism. Use this template
#define TAG_MONTH 1001
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
// any other views can be added to cell here
UILabel *month = [[UILabel alloc] initWithFrame:CGRectMake(8, 10, 53, 21)];
month.font = cellFont3;
month.textAlignment = UITextAlignmentCenter;
month.backgroundColor = [UIColor clearColor];
month.tag = TAG_MONTH;
}
// here you should fill all fields of cell with "entry" or make it empty
NSString currentmonth = #"something";
UILabel *month = [cell.contentView viewWithTag:TAG_MONTH];
month.text = currentmonth;
return cell;
}
Other moments :
you shouldn't init formatter in loop, init it once.
Exctract it into new method
if ([monthfromdate isEqualToString:#"01"]) {
self.currentmonth = #"January";
}
and optimize, it can be simpler
Check the number this method is returning, may be its returning 2
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

UITableView custom cells always change there content - must stop it

i have a UITableView with custom cells (code below) that load the data from NSDictionary (the NSDictionary loads there data from NSArray objectatIndexPath:indexpath.row.
Now, i have a DidSelectRow functions that works in the same way (NSArray -> NSDictionary -> Cell data).
the problem is that when im scrolling my table its change my cells contant.
i must have my cells always reload that same order. and i must stop this reloading data when scrolling.
This is the code im using to load my table view and load data to table view cells and my didSelectRow: Please help, i dont have time for this problem...
RequestArray = [jsonDictionary objectForKey:#"Content"];
RequestTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 84, 320, 326)];
RequestTable.backgroundColor = [UIColor colorWithRed:(234/255.f) green:(234/255.f) blue:(234/255.f) alpha:1];
RequestTable.dataSource=self;
RequestTable.delegate=self;
RequestTable.rowHeight = 77;
[self.view addSubview:RequestTable];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier];
NSDictionary *object = [RequestArray objectAtIndex:indexPath.row];
NSString *Category = [object valueForKey:#"Category"];
NSString *ItemDescription = [object valueForKey:#"ItemDescription"];
NSString *ItemName = [object valueForKey:#"ItemName"];
NSString *Date = [object valueForKey:#"Date"];
NSString *ExpiresDate = [object valueForKey:#"ExpiresDate"];
BOOL isRead = [[object valueForKey:#"IsRead"]boolValue];
/// add time label to cell
NSTimeInterval TIMEinterval = [Date intValue];
NSDate* TIMEDate = [NSDate dateWithTimeIntervalSince1970:TIMEinterval];
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm"];
[df setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:2]]; //+0000
NSString* dateStrig = [df stringFromDate:TIMEDate];
UILabel *RequestTime = [[UILabel alloc]initWithFrame:CGRectMake(268, 8, 33, 16)];
[RequestTime setTextAlignment:UITextAlignmentRight];
RequestTime.backgroundColor = [UIColor clearColor];
RequestTime.textColor = [UIColor blackColor];
[RequestTime setFont:[UIFont systemFontOfSize:12]];
RequestTime.text = dateStrig;
[cell addSubview:RequestTime];
/// add experation label to cell
NSTimeInterval EXPTIMEinterval = [ExpiresDate intValue];
NSDate* EXPDate = [NSDate dateWithTimeIntervalSince1970:EXPTIMEinterval];
NSTimeInterval secondsBetween = [EXPDate timeIntervalSinceDate:TIMEDate];
int numberOfHours = secondsBetween / 3600;
UILabel *ExperationTime = [[UILabel alloc]initWithFrame:CGRectMake(152, 24, 150, 15)];
ExperationTime.backgroundColor = [UIColor clearColor];
[ExperationTime setTextAlignment:UITextAlignmentRight];
ExperationTime.textColor = [UIColor colorWithRed:(255/255.f) green:(103/255.f) blue:(18/255.f) alpha:1];
[ExperationTime setFont:[UIFont systemFontOfSize:14]];
if (numberOfHours>24){
numberOfHours = numberOfHours/24;
ExperationTime.text = [NSString stringWithFormat:#"המוצר דרוש תוך %d ימים",numberOfHours];
}else{
ExperationTime.text = [NSString stringWithFormat:#"המוצר דרוש תוך %d שעות",numberOfHours];
}
[cell addSubview:ExperationTime];
// add item category to cell
UILabel *itamCategory = [[UILabel alloc]initWithFrame:CGRectMake(143 , 5, 120, 21)];
itamCategory.backgroundColor = [UIColor clearColor];
[itamCategory setTextAlignment:UITextAlignmentRight];
itamCategory.textColor = [UIColor colorWithRed:(0/255.f) green:(177/255.f) blue:(233/255.f) alpha:1];
[itamCategory setFont:[UIFont boldSystemFontOfSize:17]];
itamCategory.text = Category;
[cell addSubview:itamCategory];
// add item Name to cell
UILabel *itamName = [[UILabel alloc]initWithFrame:CGRectMake(98, 39, 203, 21)];
itamName.backgroundColor = [UIColor clearColor];
[itamName setTextAlignment:UITextAlignmentRight];
itamName.textColor = [UIColor blackColor];
[itamName setFont:[UIFont boldSystemFontOfSize:17]];
itamName.text = ItemName;
[cell addSubview:itamName];
// add item Description to cell
UILabel *Description = [[UILabel alloc]initWithFrame:CGRectMake(98, 62, 203, 10)];
Description.backgroundColor = [UIColor clearColor];
[Description setTextAlignment:UITextAlignmentRight];
Description.textColor = [UIColor blackColor];
[Description setFont:[UIFont systemFontOfSize:13]];
Description.text =ItemDescription;
[cell addSubview:Description];
//add sendOffer button
UIButton *callSeller = [UIButton buttonWithType:UIButtonTypeCustom];
callSeller.frame = CGRectMake(25, 8, 54, 45);
[callSeller setTag:indexPath.row];
[callSeller setBackgroundImage:[UIImage imageNamed:#"makeOfferTable.png"] forState:UIControlStateNormal];
[callSeller setBackgroundImage:[UIImage imageNamed:#"makeOfferTable.png"] forState:UIControlStateHighlighted];
[callSeller addTarget:self action:#selector(makeaOffer:) forControlEvents:UIControlEventAllEvents];
[cell addSubview:callSeller];
UIView *myBackView = [[UIView alloc] initWithFrame:cell.frame];
myBackView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"highlightCellBG.png"]];
cell.selectedBackgroundView = myBackView;
cell.backgroundColor = [UIColor lightGrayColor];
//add newOffer sign (if new)
if (!isRead){
UIImageView *newIndocator = [[UIImageView alloc]initWithFrame:CGRectMake(295, 0, 25, 25)];
newIndocator.image = [UIImage imageNamed:#"newOfferIndicator.png"];
[newIndocator setContentMode:UIViewContentModeScaleToFill];
[cell addSubview:newIndocator];
}
}
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *object = [RequestArray objectAtIndex:indexPath.row];
NSLog(#"indePath.row = %d",indexPath.row);
Seller_RequestDetailsViewController *infoView = [[Seller_RequestDetailsViewController alloc]initWithNibName:#"Seller_RequestDetailsViewController" bundle:nil];
NSString *OfferDate = [object valueForKey:#"Date"];
NSTimeInterval TIMEinterval = [OfferDate intValue];
NSDate* TIMEDate = [NSDate dateWithTimeIntervalSince1970:TIMEinterval];
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"DD/MM/yyyy"];
[df setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:2]]; //+0000
infoView.date = [df stringFromDate:TIMEDate];
infoView.itemName = [object valueForKey:#"ItemName"];
infoView.modalName = [object valueForKey:#"ItemDegem"];
infoView.buyerID = [NSString stringWithFormat:#"%#",[object valueForKey:#"BuyerUserID"]];
infoView.city = [object valueForKey:#"Region"];
infoView.Offerdescription = [object valueForKey:#"ItemDescription"];
BOOL isRead = [[object valueForKey:#"IsRead"]boolValue];
infoView.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:infoView animated:YES];
if (!isRead){
[self markOfferAsRead:[NSString stringWithFormat:#"%#",[object valueForKey:#"ItemID"]]];
}
}
I am not sure I understand your problem completely but I do see an error in the way you build the cells. After dequeueing the cell, you should only init the cell if it's nil NOT init and build the cell.
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if(cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier];
}
// Now build the cell.
If you don't rebuild the cell every time, it will just reuse the cell that was originally built.
your problem is that everything is with in this:
if(cell == nil) {
//Your Code
}
What is happening is the tableview reuses cells. You are only changing the content if(cell == nil).
What you need is to only create a new cell in side if(cell == nil)
and move the rest of your code out of that if statement

Insert NSarray items into specified UItableviewcell

I have a UItableview with 10 cells.I need to display a message from an NSarray into this tableview.The array contains 3 items and needs to be displayed in the any of the 3 cells .
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomTableView *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[ CustomTableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString *order = [orderArray objectAtIndex:indexPath.row];
NSString *sdate = [dateArray objectAtIndex:indexPath.row];
//Label positions
UILabel *ordernum = [[UILabel alloc] initWithFrame:CGRectMake(5,28,95,21)];
UILabel *date = [[UILabel alloc] initWithFrame:CGRectMake(100,28,80,21)];
UILabel *orderStatusMessage = [[UILabel alloc] initWithFrame:CGRectMake(200,28,80,21)];
NSString *ordertypeName = [ordertypeArray objectAtIndex:indexPath.row];
ordernum.textColor = [UIColor blackColor];
[cell.contentView addSubview:ordernum];
date.textColor = [UIColor blackColor];
[cell.contentView addSubview:date];
orderStatusMessage.textColor = [UIColor blackColor];
if ([ordertypeName isEqualToString:#"saved"]) {
ordernum.text = [NSString stringWithString:#"Saved Order"];
date.text = [NSString stringWithFormat:#"%#",sdate];
}
else{
if (![order isEqualToString:#""]) {
for (int i=0; i<[reversed count]; i++)
{
stat=[reversed objectAtIndex:i];
}
}
ordernum.text = [NSString stringWithFormat:#"%#",order];
date.text = [NSString stringWithFormat:#"%#",sdate];
orderStatusMessage.text =[NSString stringWithFormat:#"%#",stat];
[cell.contentView addSubview:orderStatusMessage];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleGray;
// }
return cell;
}
With the above code I am getting only the last item from reversed array.Please help
To start, your for loop is bogus
if (![order isEqualToString:#""]) {
for (int i=0; i<[reversed count]; i++)
{
stat=[reversed objectAtIndex:i];
}
}
Why are you looping and overwriting the reference to stat with each iteration? That's clearly not your intent.
Second, I would advise refactoring, since this code snippit is extremely confusing and it is very close to impossible to understand the intent. Please repost after renaming variables and cleaning the code a bit.

How to load data in two section of table view iPhone

I have 2 sections within a table view and I have loaded one section from one array and one from another. How can I set cell values for both sections?
I'm using the following code:
Title For Header Section.
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection: (NSInteger)section
{
if(section == 0)
return #" Scheduled Patients ";
else
return #" Walk In Patients ";
}
Rows in Section:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(section==0)
return [resultArray count];
else {
EMRAppDelegate *appDelegate = (EMRAppDelegate *)[[UIApplication sharedApplication] delegate];
return [appDelegate.walkPatients count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UIButton * uploadButton = nil;
static NSString * Identifier = #"Identifier";
UITableViewCell * cell = [table dequeueReusableCellWithIdentifier:Identifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:Identifier] autorelease];
uploadButton = [UIButton buttonWithType:UIButtonTypeCustom];
[uploadButton setFrame:CGRectMake(10, 10, 24, 24)];
[uploadButton setImage:[UIImage imageNamed:#"upload.png"] forState:UIControlStateNormal];
[uploadButton addTarget:self action:#selector(onUploadButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[uploadButton setTag:999];
cell.accessoryView = uploadButton;
}
else {
uploadButton = (UIButton *)cell.accessoryView;
}
EMRAppDelegate *appDelegate = (EMRAppDelegate *)[[UIApplication sharedApplication] delegate];
ObjectData *theCellData =[resultArray objectAtIndex:indexPath.row];
WalkPatient * patient = [ appDelegate.walkPatients objectAtIndex:indexPath.row];
if (indexPath.section == 0)
{
// do coding for cell loading for Scheduled Patients
cell.textLabel.font = [UIFont systemFontOfSize:18];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", theCellData.firstName, theCellData.lasttName];
if (patient.syncDate != nil) {
UIImageView * checkmark = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"right.png"]];
[checkmark setFrame:CGRectMake(12, 0, 12, 12)];
[checkmark setTag:998];
[uploadButton addSubview:checkmark];
[checkmark release];
[uploadButton removeTarget:self action:#selector(onUploadButtonClick:) forControlEvents:UIControlEventTouchUpInside];
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy hh:mm"];
cell.detailTextLabel.font = [UIFont systemFontOfSize:12];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Synched: %#", [dateFormatter stringFromDate:patient.syncDate]];
[dateFormatter release];
}
else {
UIView * checkmark = (UIView *)[uploadButton viewWithTag:998];
if (checkmark != nil) {
[checkmark removeFromSuperview];
}
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
else
{
// do load cells for Walk In Patients.
cell.textLabel.font = [UIFont systemFontOfSize:18];
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", patient.firstName, patient.lastName];
if (patient.syncDate != nil) {
UIImageView * checkmark = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"right.png"]];
[checkmark setFrame:CGRectMake(12, 0, 12, 12)];
[checkmark setTag:998];
[uploadButton addSubview:checkmark];
[checkmark release];
[uploadButton removeTarget:self action:#selector(onUploadButtonClick:) forControlEvents:UIControlEventTouchUpInside];
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy hh:mm"];
cell.detailTextLabel.font = [UIFont systemFontOfSize:12];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Synched: %#", [dateFormatter stringFromDate:patient.syncDate]];
[dateFormatter release];
}
else {
UIView * checkmark = (UIView *)[uploadButton viewWithTag:998];
if (checkmark != nil) {
[checkmark removeFromSuperview];
}
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
}
Its simple. In cellForRowAtIndexPath method also you put one condition to check the section and load data according to them.
if (indexPath.section == 0)
{
// do coding for cell loading for Scheduled Patients
UIButton *btnsection0=[UIButton buttonWithType:UIButtonTypeCustom];
[btnsection0 addTarget:self action:#selector(showProject:) forControlEvents:UIControlEventTouchUpInside];
}
else
{
// do load cells for Walk In Patients.
UIButton *btnsection1=[UIButton buttonWithType:UIButtonTypeCustom];
[btnsection0 addTarget:self action:#selector(showProject:) forControlEvents:UIControlEventTouchUpInside];
}
You've almost got it. The cellForRowAtIndexPath method comes with an indexPath parameter that can give you:
NSInteger row = indexPath.row;
NSInteger section = indexPath.section;
Please, always, always make cellForRowAtIndexPath logic mirror the numberOfRowsInSection logic, so when you get asked for a row count:
return (section==0)? [array0 count] : [array1 count];
... and when you get asked for a cell, and you need the data for that cell
NSInteger row = indexPath.row;
NSInteger section = indexPath.section;
NSArray *arrayForThisSection = (section==0)? array0 : array1;
id elementForThisRow = [arrayForThisSection objectAtIndex:row];
// config the cell with elementForThisRow
From the documentation for UITableViewDataSource:
UITableView declares a category on NSIndexPath that enables you to get the represented row index (row property) and section index (section property),
So you can go indexPath.section and it'll tell you which section the tableview wants to populate.
UIButton *btnsection0=[UIButton buttonWithType:UIButtonTypeCustom];
if (indexPath.section == 0)
{
btnsection0.tag = [NSString stringWithFormat:#"%d%d",indexPath.section,indexPath.row];
}else{
btnsection0.tag = [NSString stringWithFormat:#"%d%d",indexPath.section,indexPath.row];
}
[btnsection0 addTarget:self action:#selector(showProject:) forControlEvents:UIControlEventTouchUpInside];
button event
-(IBAction)showProject:(id)sender{
NSString *s = [NSString stringWithFormat:#"%d%d",indexPath.section,indexPath.row];
int section = [[s substringToIndex:1] intValue];
int row = [[s substringFromIndex:0] intValue];
}

UITableView Custom Cell very slow

I have a UITableView and I have created a custom cell to display my table. I have 6 UILables displayed and although I have only 20 records to show, it is very slow when I scroll.
This is how my - tableView: cellForRowAtIndexPath: looks like:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CustomCellIdentifier = #"CustomCellIdentifier";
HistoryCell *cell = (HistoryCell *)[tableView dequeueReusableCellWithIdentifier: CustomCellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"HistoryCell" owner:nil options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[UITableViewCell class]])
cell = (HistoryCell *) oneObject;
}
NSArray *object;
object = [cours objectForKey: [NSString stringWithFormat:#"%d", indexPath.section]];
History *rowData = [object objectAtIndex:indexPath.row];
if (rowData.month == 99) {
cell.hour.frame = CGRectMake(10, 0, 135, 35);
cell.data.hidden = YES;
cell.hour.textColor = [UIColor blackColor];
cell.hour.font = [UIFont fontWithName:#"Verdana" size:17];
} else {
cell.data.hidden = NO;
cell.hour.frame = CGRectMake(10, 16, 135, 19);
cell.hour.textColor = [UIColor grayColor];
cell.hour.font = [UIFont fontWithName:#"Verdana" size:12];
}
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"d (EEEE)"];
[formatter setLocale:self.selectedLanguageLocale];
NSString *stringFromDate = [formatter stringFromDate:rowData.data];
[formatter release];
cell.data.text = stringFromDate;
cell.hour.text = rowData.ora;
float Var1 = [rowData.Var2 floatValue];
float Var2 = [rowData.Var2 floatValue];
cell.R1.text = [self floatToStringFormat: [rowData.R1 floatValue]];
cell.R2.text = [self floatToStringFormat: [rowData.R2 floatValue]];
if (Var1 <= 0) {
cell.Var1.textColor = [UIColor greenColor];
} else {
cell.Var1.textColor = [UIColor redColor];
}
if (Var2 <= 0) {
cell.Var2.textColor = [UIColor greenColor];
} else {
cell.Var2.textColor = [UIColor redColor];
}
cell.Var1.text = [self floatToStringFormat:Var1];
cell.Var2.text = [self floatToStringFormat:Var2];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
The reason for running that slow on scroll is because of all the things I am doing here (NSDateFormatter, CGMakeRect, floatToStringFormat...) or is there something wrong with reusing cells?
floatToStringFormat is a function to format a number to 4 decimals:
- (NSString *)floatToStringFormat:(float)number{
NSNumberFormatter *myFloat = [[NSNumberFormatter alloc] init];
[myFloat setFormatterBehavior:NSNumberFormatterBehavior10_4];
[myFloat setNumberStyle:NSNumberFormatterDecimalStyle];
[myFloat setRoundingMode:NSNumberFormatterRoundHalfUp];
[myFloat setMinimumFractionDigits:4];
[myFloat setMaximumFractionDigits:4];
NSString *res = [myFloat stringFromNumber:[NSNumber numberWithFloat:number]];
[myFloat release];
return res;
}
Creating and setting up formatter objects is an expensive operation indeed, so I'd start with reusing your formatter objects since they are the same on each function call. So either make them static variables or instant variables in your data source class and create the following way:
//static variable case
NSDateFormatter *formatter = nil;
if (!formatter){
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"d (EEEE)"];
[formatter setLocale:self.selectedLanguageLocale];
}
NSString *stringFromDate = [formatter stringFromDate:rowData.data];
...
Firstly, you are using two different identifiers: CustomCellIdentifier and BanciHistoryCellIdentifier.
Secondly, do you really need to do everything after NSArray *object; every time a new cell is displayed? Because if you don't, you should move it to the if (cell == nil) { block.
From my experience the drawing of table view cells is significantly slowed down if you have three or more subviews (also depends on the device and the views though). Try to directly draw the content in drawRect: instead of using subviews, this should speed things up.
What are you doing here:
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"HistoryCell" owner:nil options:nil];
for (id oneObject in nib)
if ([oneObject isKindOfClass:[UITableViewCell class]])
cell = (HistoryCell *) oneObject;
}
Go read the documentation on how to do this properly. Secondly, if this is taking too long to convert the dates and numbers to strings then store the string values instead, and turn them into values when you need to modify them.
Do you have the CellIdentifier set in Interface builder? It must match exactly what you are using in code. Set a breakpoint where it loads the cell from the nib and make sure it's reusing cells when you scroll.