TableView slows down after scrolling up and down a few times - ios

I have a tableview in xcode that currently downloads from the parse.com backend and displays into the table. It will download a small image and render the image into a circle as well as style each row. Currently it is downloading about 5 rows and outputs lovely but as soon as i scroll up and down a few times the tableview and app becomes slow.
Doing some research i can see suggestions to add the fetching of data on another thread. Currently i am new to all this and i was wondering if any one could assist in showing me how it's done.
My CellForRowAtIndexPath looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
tableView.separatorColor = [UIColor colorWithRed:192.0/255.0 green:196.0/255.0 blue:202.0/255.0 alpha:1];
if ([self.tableView respondsToSelector:#selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if (cell == nil)
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
PFObject *games = [self.games objectAtIndex:indexPath.row];
//PFFile *imageFile = [games objectForKey:#"gameCover"];
NSString *gameName = [games objectForKey:#"name"];
NSArray *gamePlatforms = [games objectForKey:#"platform"];
NSString *platformsResult = [gamePlatforms componentsJoinedByString:#""];
NSDate *rDate = [games objectForKey:#"release_date"];
// Check to see if the date is set to a Quarter instead
if (rDate == (id)[NSNull null]) {
self.releaseDate = #"Q1/2014";
} else {
// Date on the right added to a subview
//Setup date
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
//uncomment to get the time only
//[formatter setDateFormat:#"hh:mm a"];
[formatter setDateFormat:#"dd"];
//[formatter setDateStyle:NSDateFormatterLongStyle];
//get the date today
NSDate *start = [NSDate date];
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"YYYY-MM-dd"];
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [gregorianCalendar components:NSDayCalendarUnit
fromDate:start
toDate:rDate
options:0];
//NSLog(#"%ld", (long)[components day]);
NSInteger value = [components day];
NSString *myString = [NSString stringWithFormat:#"%0.0f days", (float)value];
if ([myString isEqual: #"1 days"])
{
myString = #"1 day";
}
self.releaseDate = myString;
}
// Cell Style
// Background Color
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 15, 300.0, 100.0)];
imageView.userInteractionEnabled = NO;
imageView.backgroundColor = [UIColor colorWithRed:209.0/255.0 green:230.0/255.0 blue:244.0/255.0 alpha:1];
// Icon Image
//Game Title Label
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(80, 25, 200, 20)];
titleLabel.text = gameName;
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.font = [UIFont fontWithName:#"ProximaNova-Light" size:13];
titleLabel.textColor = [UIColor colorWithRed:44.0/255.0 green:127.0/255.0 blue:178.0/255.0 alpha:1];
// Game Date Label
UILabel *dateLabel = [[UILabel alloc]initWithFrame:CGRectMake(250, 80, 50, 20)];
dateLabel.text = self.releaseDate;
dateLabel.backgroundColor = [UIColor clearColor];
dateLabel.font = [UIFont fontWithName:#"ProximaNova-Light" size:13];
dateLabel.textColor = [UIColor colorWithRed:44.0/255.0 green:127.0/255.0 blue:178.0/255.0 alpha:1];
dateLabel.textAlignment = NSTextAlignmentRight;
// Game Platforms
UILabel *platformLabel = [[UILabel alloc]initWithFrame:CGRectMake(250, 25, 50, 20)];
platformLabel.text = platformsResult;
platformLabel.backgroundColor = [UIColor clearColor];
platformLabel.font = [UIFont fontWithName:#"ProximaNova-Light" size:13];
platformLabel.textColor = [UIColor colorWithRed:44.0/255.0 green:127.0/255.0 blue:178.0/255.0 alpha:1];
platformLabel.textAlignment = NSTextAlignmentRight;
// add the styles to the subview
[cell addSubview:imageView];
//[cell addSubview:iconView];
[cell addSubview:titleLabel];
[cell addSubview:dateLabel];
[cell addSubview:platformLabel];
PFFile *imageFile = [games objectForKey:#"gameCover"];
// If no image
if (imageFile != NULL) {
NSURL *imageFileUrl = [[NSURL alloc] initWithString:imageFile.url];
NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl];
UIImage *myImage = [UIImage imageWithData:imageData];
UIImageView *iconView = [[UIImageView alloc] initWithImage:myImage];
iconView.frame = CGRectMake(20.0, 25.0, 50.0, 50.0);
iconView.layer.masksToBounds = YES;
iconView.layer.cornerRadius = 25.0f;
[cell addSubview:iconView];
} else {
UIImageView *iconView = [[UIImageView alloc]initWithFrame:CGRectMake(20.0, 25.0, 50.0, 50.0)];
iconView.userInteractionEnabled = NO;
iconView.image = [UIImage imageNamed:#"img.png"];
iconView.layer.masksToBounds = YES;
iconView.layer.cornerRadius = 25.0f;
[cell addSubview:iconView];
}
return cell;
}
Sorry for the mess, i can post more code if anyone would like it.
Thanks

Hmmm, U R constantly adding views to UITableViewCell:
[cell addSubview:imageView];
//[cell addSubview:iconView];
[cell addSubview:titleLabel];
[cell addSubview:dateLabel];
[cell addSubview:platformLabel];
U should add them only once in if(cell == nil) block cause they R reusable cells..
Do it like this:
if (cell == nil)
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
// Cell Style
// Background Color
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 15, 300.0, 100.0)];
[imageView setTag:100];
imageView.userInteractionEnabled = NO;
imageView.backgroundColor = [UIColor colorWithRed:209.0/255.0 green:230.0/255.0 blue:244.0/255.0 alpha:1];
//Game Title Label
UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(80, 25, 200, 20)];
[titleLabel setTag:101];
titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.font = [UIFont fontWithName:#"ProximaNova-Light" size:13];
titleLabel.textColor = [UIColor colorWithRed:44.0/255.0 green:127.0/255.0 blue:178.0/255.0 alpha:1];
// Game Date Label
UILabel *dateLabel = [[UILabel alloc]initWithFrame:CGRectMake(250, 80, 50, 20)];
[dateLabel setTag:102];
dateLabel.backgroundColor = [UIColor clearColor];
dateLabel.font = [UIFont fontWithName:#"ProximaNova-Light" size:13];
dateLabel.textColor = [UIColor colorWithRed:44.0/255.0 green:127.0/255.0 blue:178.0/255.0 alpha:1];
dateLabel.textAlignment = NSTextAlignmentRight;
// Game Platforms
UILabel *platformLabel = [[UILabel alloc]initWithFrame:CGRectMake(250, 25, 50, 20)];
[platformLabel setTag:103];
platformLabel.text = platformsResult;
platformLabel.backgroundColor = [UIColor clearColor];
platformLabel.font = [UIFont fontWithName:#"ProximaNova-Light" size:13];
platformLabel.textColor = [UIColor colorWithRed:44.0/255.0 green:127.0/255.0 blue:178.0/255.0 alpha:1];
platformLabel.textAlignment = NSTextAlignmentRight;
// add the styles to the subview
[cell addSubview:imageView];
//[cell addSubview:iconView];
[cell addSubview:titleLabel];
[cell addSubview:dateLabel];
[cell addSubview:platformLabel];
......
}
UILabel *lbl = [cell viewWithTag:101];
lbl.text = gameName;
lbl = [cell viewWithTag:102];
lbl.text = self.releaseDate;
lbl = [cell viewWithTag:103];
lbl.text = platformsResult;
Do the same thing for your ImageViews, and U will enter the world of reusability and fast tables :)
And also U shouldn't download images like that, U should use some async approach like others recomended

Because you are downloading images in cellForRowAtIndexPath. You must have to download images Asynchronously. Because of this performance of application will be increase. So try to download asynchronously.

Use this code to download your image asynchronously in your cellForRowAtIndexPath
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:parsedData[#"imageLR"]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.tag == indexPath.row) {
cell.imageView.image = image;
[cell setNeedsLayout];
}
});
}
});

replace the code in if no image with this
// If no image
if (imageFile != NULL) {
NSURL *imageFileUrl = [[NSURL alloc] initWithString:imageFile.url];
dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("Image Downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl];
dispatch_async(callerQueue, ^{
UIImage *myImage = [UIImage imageWithData:imageData];
UIImageView *iconView = [[UIImageView alloc] initWithImage:myImage];
iconView.frame = CGRectMake(20.0, 25.0, 50.0, 50.0);
iconView.layer.masksToBounds = YES;
iconView.layer.cornerRadius = 25.0f;
[cell addSubview:iconView];
});
});
}

User SDWebImageCache
Image is download in background by this class and Image caching in handle by this class, And your table will scroll smooth Follow this link Here:

Related

UITableView crashes on scroll (memory warnings)

I have made my first UITableView, but when the number of cells is higher than what can be shown on the screen, and I scroll, it then crashes because of lack of memory.
I implemented the SDWEBIMAGE library to load the pictures async. and cache the images afterwards.
If more code is needed, please let me know !
I am a complete newbie at this, so please be gentle :)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *myIdentifier = #"defaultcell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:myIdentifier forIndexPath:indexPath];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:myIdentifier];
}
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(160, 47);
[spinner startAnimating];
[cell.contentView addSubview:spinner];
//hide labels until done loading
cell.textLabel.hidden = YES;
cell.detailTextLabel.hidden = YES;
cell.imageView.hidden = YES;
UIImageView *iv = [[UIImageView alloc] initWithFrame:(CGRect){.size={80, 60}}];
iv.contentMode = UIViewContentModeScaleAspectFill;
iv.clipsToBounds = YES;
iv.frame = CGRectMake(15, 17, 80, 60);
NSString *profilePicName = [NSString stringWithFormat:#"%#%#", [self.dbhandler getPicturesPath], [[gallery objectAtIndex:indexPath.row] valueForKey: #"filename"]];
[iv setImageWithURL:[NSURL URLWithString:profilePicName] placeholderImage:[UIImage imageNamed:#"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType){
[spinner stopAnimating];
cell.textLabel.hidden = NO;
cell.detailTextLabel.hidden = NO;
cell.imageView.hidden = NO;
[cell.contentView addSubview:iv];
}];
NSString *subtitle = [NSString stringWithFormat:#"Comments: %# \nPosted: %#", [[gallery objectAtIndex:indexPath.row] valueForKey:#"comments"], [[gallery objectAtIndex:indexPath.row] valueForKey:#"created_at"]];
cell.detailTextLabel.numberOfLines = 0;
cell.textLabel.text = [NSString stringWithFormat:#"Votes: %#",[[gallery objectAtIndex:indexPath.row] valueForKey:#"votes"]];
cell.detailTextLabel.text = subtitle;
return cell;
}
UPDATED FUNCTION:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *myIdentifier = #"defaultcell";
UIActivityIndicatorView *spinner;
UIImageView *iv;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:myIdentifier forIndexPath:indexPath];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:myIdentifier];
//build spinner
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(160, 47);
spinner.tag = 101;
[cell.contentView addSubview:spinner];
//build ImageView
iv = [[UIImageView alloc] initWithFrame:(CGRect){.size={80, 60}}];
iv.contentMode = UIViewContentModeScaleAspectFill;
iv.clipsToBounds = YES;
iv.tag = 102;
iv.frame = CGRectMake(15, 17, 80, 60);
[cell.contentView addSubview:iv];
} else {
spinner = (UIActivityIndicatorView*)[cell viewWithTag:101];
iv = (UIImageView*)[cell viewWithTag:102];
}
[spinner startAnimating];
//the rest goes here
cell.textLabel.hidden = YES;
cell.detailTextLabel.hidden = YES;
cell.imageView.hidden = YES;
NSString *profilePicName = [NSString stringWithFormat:#"%#%#", [self.dbhandler getPicturesPath], [[gallery objectAtIndex:indexPath.row] valueForKey: #"filename"]];
NSLog(#"%#", profilePicName);
[iv setImageWithURL:[NSURL URLWithString:profilePicName] placeholderImage:[UIImage imageNamed:#"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType){
[spinner stopAnimating];
cell.textLabel.hidden = NO;
cell.detailTextLabel.hidden = NO;
cell.imageView.hidden = NO;
NSLog(#"done");
[cell.contentView addSubview:(UIImageView *)[cell viewWithTag:102]];
}];
NSString *subtitle = [NSString stringWithFormat:#"Comments: %# \nPosted: %#", [[gallery objectAtIndex:indexPath.row] valueForKey:#"comments"], [[gallery objectAtIndex:indexPath.row] valueForKey:#"created_at"]];
cell.detailTextLabel.numberOfLines = 0;
cell.textLabel.text = [NSString stringWithFormat:#"Votes: %#",[[gallery objectAtIndex:indexPath.row] valueForKey:#"votes"]];
cell.detailTextLabel.text = subtitle;
return cell;
}
Every-time you reuse a cell you are adding the UIActivityIndicatorView/spinner and UIImageView/iv as subviews. Better approach is to use a custom Prototype cell in the storyboard or reuse existing views by setting a Tag.
UIActivityIndicatorView *spinner;
UIImageView *iv;
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:myIdentifier];
//build spinner
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(160, 47);
spinner.tag = 101;
[cell.contentView addSubview:spinner];
//build ImageView
iv = [[UIImageView alloc] initWithFrame:(CGRect){.size={80, 60}}];
iv.contentMode = UIViewContentModeScaleAspectFill;
iv.clipsToBounds = YES;
iv.tag = 102;
iv.frame = CGRectMake(15, 17, 80, 60);
[cell.contentView addSubview:iv];
} else {
spinner = (UIActivityIndicatorView*)[cell.contentView viewWithTag:101];
iv = (UIImageView*)[cell.contentView viewWithTag:102];
}
[spinner startAnimating];
//the rest goes here
You need to remove other addSubView calls(specifically in the callback block).
This should help you to get started.

get class variables from nsobject stored in msmutablearray

I have a class Vehicle which is an NSOBject. It has 4 string variables vrn, make, model, yearmade. I am crating the Vehicle objects from data which i get through a webservice and store each object in an nsmutablearray. How can i access the variables vrn, make, model, yearmade from the mutable array for each stored object?
Edit:
I have tried this:
[[myArray objectAtIndex:indexPath.row] objectAtIndex:0];
Edit 2:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//NSLog(#"test");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
if ([tableView isEqual:vrnTable]) {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.opaque = NO;
vrnLabel = [[UILabel alloc] initWithFrame:CGRectMake(60.0, 7.0, 50.0, 30.0)];
vrnLabel.font = [UIFont systemFontOfSize:12.0];
vrnLabel.textAlignment = UITextAlignmentRight;
vrnLabel.textColor = [UIColor whiteColor];
vrnLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
vrnLabel.backgroundColor = [UIColor clearColor];
vrnLabel.tag = VRN_LABEL_TAG;
[cell.contentView addSubview:vrnLabel];
makeLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 7.0, 10.0, 30.0)];
makeLabel.font = [UIFont systemFontOfSize:12.0];
makeLabel.textAlignment = UITextAlignmentRight;
makeLabel.textColor = [UIColor whiteColor];
makeLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
makeLabel.backgroundColor = [UIColor clearColor];
makeLabel.tag = MAKE_LABEL_TAG;
[cell.contentView addSubview:makeLabel];
modelLabel = [[UILabel alloc] initWithFrame:CGRectMake(200.0, 7.0, 10.0, 30.0)];
modelLabel.font = [UIFont systemFontOfSize:12.0];
modelLabel.textAlignment = UITextAlignmentRight;
modelLabel.textColor = [UIColor whiteColor];
modelLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
modelLabel.backgroundColor = [UIColor clearColor];
modelLabel.tag = MODEL_LABEL_TAG;
[cell.contentView addSubview:modelLabel];
yearLabel = [[UILabel alloc] initWithFrame:CGRectMake(120.0, 7.0, 10.0, 30.0)];
yearLabel.font = [UIFont systemFontOfSize:12.0];
yearLabel.textAlignment = UITextAlignmentRight;
yearLabel.textColor = [UIColor whiteColor];
yearLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight;
yearLabel.backgroundColor = [UIColor clearColor];
yearLabel.tag = YEAR_LABEL_TAG;
[cell.contentView addSubview:yearLabel];
}
else {
vrnLabel = (UILabel *)[cell.contentView viewWithTag:VRN_LABEL_TAG];
}
}
NSString *cell_image = [NSString alloc];
if (indexPath.row != 0) {
cell_image = [NSString stringWithFormat:#"color%d.png", indexPath.row % 8 + 1];
}
else {
cell_image = [NSString stringWithFormat:#"color%d.png", 0];
}
cell.backgroundView = [[UIImageView alloc] initWithImage:[ [UIImage imageNamed:cell_image] stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0] ];
vrnLabel.text = ((Vehicle *)[entries objectAtIndex:indexPath.row]).vrn;
return cell;
}
Simple thing, just use objectAtIndex and use typecast to access object variable:
NSString *firstObjVrn = ((Vehicle*)[vehicleArray objectAtIndex:indexPath.row]).vrn;
NSString *firstObjMake = ((Vehicle*)[vehicleArray objectAtIndex:indexPath.row]).make;
NSString *firstObjModel = ((Vehicle*)[vehicleArray objectAtIndex:indexPath.row]).model;
NSString *firstObjYearMade = ((Vehicle*)[vehicleArray objectAtIndex:indexPath.row]).yearMade;

uitableview reloaddata cache?

I'm having some problems with an UITableView and the method reloadData.
I'm refreshing the tableView when clicking over a refresh button with the last info in a data base ordered descendingly so the most recent items should appear in first position.
Every cell in my tableview is being filled with custom labels and uiimageviews.
Well... the thing is that when I press that refresh button and new data is found, the first 5 rows (which are the ones that are being shown in the display) aren't updated but the following rows do. However, if I press over any of the 5 first rows, they call correctly to the tableView:didSelectRowAtIndexPath: method with the new data.
So, the problem is that the tableview's "visual" content of the first 5 rows is not being updated.
Anyone can help me with this?
Thanks!
Code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [ NSString stringWithFormat: #"%d:%d", [ indexPath indexAtPosition: 0 ], [ indexPath indexAtPosition:1 ]];
UITableViewCell *cell = [ tableView dequeueReusableCellWithIdentifier: CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame: CGRectZero reuseIdentifier: CellIdentifier] autorelease];
// Configure the cell...
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
Activity *activity = [[self.activities valueForKey:[[[self.activities allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text=#"";
//Mostramos el nombre
UILabel *label= [[UILabel alloc] initWithFrame:CGRectMake(60, -5, 200, 34)];
label.text = [activity name];
label.font = [UIFont boldSystemFontOfSize:17];
label.backgroundColor = [UIColor clearColor];
[cell addSubview:label];
[label release];
//Mostramos la imagen
UIImageView *leftImage = [[UIImageView alloc] initWithFrame:CGRectMake(5, 3, 50, 50)];
[cell addSubview:leftImage];
UITextView *textView=[[UITextView alloc] initWithFrame:CGRectMake(60, 25, 200, 38)];
textView.editable = NO;
textView.backgroundColor = [UIColor clearColor];
textView.textColor = [UIColor grayColor];
textView.font = [UIFont systemFontOfSize:12.0];
textView.contentInset = UIEdgeInsetsMake(-8,-8,0,0);
textView.userInteractionEnabled=NO;
[cell addSubview:textView];
switch ([activity notType]) {
case 0:
textView.text = [NSString stringWithFormat:NSLocalizedString(#"requestPUSH",#""),[activity name]];
leftImage.image = [UIImage imageNamed:#"ios.png"];
break;
case 1:
textView.text = [NSString stringWithFormat:NSLocalizedString(#"MPCreatedPushString",#""),[activity name],[activity nameItem]];
leftImage.image = [UIImage imageNamed:#"mpNew.png"];
break;
case 2:
textView.text = [NSString stringWithFormat:NSLocalizedString(#"MPUpdatedPushString",#""),[activity name],[activity nameItem]];
leftImage.image = [UIImage imageNamed:#"mpUpdated.png"];
break;
case 3:
textView.text = [NSString stringWithFormat:NSLocalizedString(#"MPDeletedPushString",#""),[activity name],[activity nameItem]];
leftImage.image = [UIImage imageNamed:#"ios.png"];
break;
case 4:
textView.text = [NSString stringWithFormat:NSLocalizedString(#"MPGuestConfirmationPUSHString",#""),[activity name],[activity nameItem]];
leftImage.image = [UIImage imageNamed:#"attend.png"];
break;
case 5:
if ([[activity message] isEqualToString:#"noData"]) {
textView.text = [NSString stringWithFormat:NSLocalizedString(#"ShoutPushString",#""),[activity name]];
}else{
textView.text = [NSString stringWithFormat:NSLocalizedString(#"ShoutPushStringWithData",#""),[activity name], [activity message]];
}
UIImage *contactImage = [UIImage imageWithData:[[activity person] pic]];
if (contactImage!=nil) {
leftImage.image = contactImage;
//redondeamos bordes
CALayer * l = [leftImage layer];
[l setMasksToBounds:YES];
[l setCornerRadius:5.0];
}else{
leftImage.image = [UIImage imageNamed:#"ios.png"];
}
break;
case 6:
textView.text = [NSString stringWithFormat:NSLocalizedString(#"CheckinPushString",#""),[activity name],[activity nameItem]];
leftImage.image = [UIImage imageNamed:#"ios.png"];
break;
case 7:
textView.text = [NSString stringWithFormat:NSLocalizedString(#"MPGuestRejectionPUSHString",#""),[activity name],[activity nameItem]];
leftImage.image = [UIImage imageNamed:#"reject.png"];
break;
default:
break;
}
[leftImage release];
[textView release];
//Mostrar fecha
double timestamp = [[activity datetime] doubleValue]/1000;
NSString *dateShow;
NSDate *datetime = [NSDate dateWithTimeIntervalSince1970:timestamp];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"HH:mm"];
dateShow=[dateFormat stringFromDate:datetime];
UILabel *label2= [[UILabel alloc] initWithFrame:CGRectMake(240, 0, 70, 20)];
label2.text = dateShow;
label2.textAlignment = UITextAlignmentRight;
label2.font = [UIFont systemFontOfSize:12];
label2.backgroundColor = [UIColor clearColor];
label2.textColor = [UIColor blueColor];
[cell addSubview:label2];
[label2 release];
}
return cell;
}
Hmm, so you give each cell a unique cell identifier. Do you have a reason for that?
Mostly people try to patch their misunderstanding of iOS table views that way ...
When you reload your table this call UITableViewCell *cell = [ tableView dequeueReusableCellWithIdentifier: CellIdentifier];
will get you a cell to reuse (read already contains content).
But your code only works for "fresh" cells : if (cell == nil) {
, you're just not prepared for that case ...

Reload UITableview data in cell out of view

[self.countryList reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:6 inSection:0], nil] withRowAnimation:UITableViewRowAnimationNone]; // or NO ;)
My problem is that I have a tableview with 10+ items with only 6 cells in view, but when the data is loaded and the table is scrolled cell 7 has no data in it. How can I reload the data in that 1 cell?
The code above is what I am using and it doesn't work!
---EDIT---
if (cell == nil) {
cell =[[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:identifier]autorelease];
//[cell setBackgroundColor: [UIColor clearColor]];
mainLabel = [[[UILabel alloc] initWithFrame:CGRectMake(52.0, 0.0, 200.0, 20.0)] autorelease];
mainLabel.tag = 1;
mainLabel.font = [UIFont systemFontOfSize:14.0];
mainLabel.textAlignment = UITextAlignmentLeft;
mainLabel.textColor = [UIColor blackColor];
mainLabel.opaque = YES;
mainLabel.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:mainLabel];
revenue = [[[UILabel alloc] initWithFrame:CGRectMake(52.0, 20.0, 150.0, 20.0)] autorelease];
revenue.tag = 3;
revenue.font = [UIFont systemFontOfSize:14.0];
revenue.textAlignment = UITextAlignmentLeft;
revenue.textColor = [UIColor blackColor];
revenue.opaque = YES;
revenue.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:revenue];
promos = [[[UILabel alloc] initWithFrame:CGRectMake(252.0, 20.0, 150.0, 20.0)] autorelease];
promos.tag = 4;
promos.font = [UIFont systemFontOfSize:14.0];
promos.textAlignment = UITextAlignmentLeft;
promos.textColor = [UIColor blackColor];
promos.opaque = YES;
promos.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:promos];
updates = [[[UILabel alloc] initWithFrame:CGRectMake(252.0, 0.0, 200.0, 20.0)] autorelease];
updates.tag = 5;
updates.font = [UIFont systemFontOfSize:14.0];
updates.textAlignment = UITextAlignmentLeft;
updates.textColor = [UIColor blackColor];
updates.opaque = YES;
updates.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:updates];
photo = [[[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 50.0)] autorelease];
photo.contentMode= UIViewContentModeScaleToFill;
photo.tag = 2;
photo.opaque = YES;
photo.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:photo];
}
else {
cell.clearsContextBeforeDrawing=YES;
mainLabel = (UILabel *)[cell.contentView viewWithTag:1];
photo = (UIImageView *)[cell.contentView viewWithTag:2];
promos=(UILabel *)[cell.contentView viewWithTag:4];
revenue=(UILabel *)[cell.contentView viewWithTag:3];
updates=(UILabel *)[cell.contentView viewWithTag:5];
if(photo.image){
photo.image=nil;
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imageURL =[NSString stringWithString:[(arrayResults*)[tweets objectAtIndex:indexPath.row] myCountryIcon]];
NSArray *myArray = [imageURL componentsSeparatedByString: #"/"];
NSString *fileName = [NSString stringWithString:[myArray lastObject]];
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/AppIcons"];
NSString* path = [dataPath stringByAppendingPathComponent:fileName];
UIImage* image = [UIImage imageWithContentsOfFile:path];
if (!image) {
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = YES;
// Create an array with the URL and name.
NSMutableArray *arr = [[NSMutableArray alloc] initWithObjects:fileName,imageURL, nil ];
[self performSelectorInBackground:#selector(loadImageInBackground:) withObject:arr];
[arr release];
}
else{
photo.image=image;
}
NSString*promostext=[[NSString alloc] initWithFormat:#"promos:%#",[[(arrayResults*)[tweets objectAtIndex:indexPath.row] mypromos]stringValue] ];
NSString*revenuetext=[[NSString alloc] initWithFormat:#"revenue:%#",[(arrayResults*)[tweets objectAtIndex:indexPath.row] myrevenue] ];
NSString*updatestext=[[NSString alloc] initWithFormat:#"updates:%#",[[(arrayResults*)[tweets objectAtIndex:indexPath.row] myupdates]stringValue] ];
mainLabel.text=[(arrayResults*)[tweets objectAtIndex:indexPath.row] myCountryName];
promos.text=promostext;
revenue.text=revenuetext;
updates.text=updatestext;
[promostext release];
[revenuetext release];
[updatestext release];
}
This is typically a misuse in the recycle/reuse mechanism of cellForRowAtIndexPath:.
Cells are reused when you scroll to avoid allocating too much UITableViewCells. So you need to set the content of the cell in cellForRowAtIndexPath: in both case, either if the cell just have been allocated (cell==nil) or if the cell has been reused (cell!=nil).

What will be the numberOfRowsInSection return type for uitableview when XML data is retrieved?

I have a NSMutableArray named as records and a NSArray.
Now I am retrieving an XML attribute and its value, using TBXML parser and inserting the attribute value in the NSArray.
This NSArray is an object of records.
What will be the numerberOfRowsInSection when I want to display the value of XML data in tableview cell?
This is my data retrieving procedure....
[records addObject:[NSArray arrayWithObjects:
[TBXML textForElement:id],
[TBXML textForElement:productNumber],
[TBXML textForElement:name],
[TBXML textForElement:availableStock],
[TBXML textForElement:image],
[TBXML textForElement:quantityOrderMin],
[TBXML textForElement:dateCreated],
[TBXML textForElement:dateUpdated],nil]];
And my XML data are....
<ProductData HASH="21106941">
<id>1</id>
<productNumber>a91cc0f4c7</productNumber>
<name>Product 1</name>
<seoTitle>product-1</seoTitle>
<viewCount>0</viewCount>
<availableStock>100.0</availableStock>
<lowStock>0.0</lowStock>
<image>5e928bbae358c93caedf6115fa7d178b.jpg</image>
<quantityOrderMax>20.0</quantityOrderMax>
<dateCreated>2011-10-06T16:08:45</dateCreated>
</ProductData>
<ProductData HASH="409555632">
<id>2</id>
<productNumber>d8287e2e51</productNumber>
<name>Product 2</name>
<seoTitle>product-2</seoTitle>
<description>
<p>Lorem ipsum dolor sit amet, consectetue...</p>
</description>
<viewCount>0</viewCount>
<availableStock>100.0</availableStock>
<image>8bbd8dfff3cdd28285d07810a4fe7c32.jpg</image>
<quantityOrderMin>1.0</quantityOrderMin>
<dateCreated>2011-10-06T16:08:45</dateCreated>
</ProductData>
I am being able to retrieve data in UITableviewCell, but it's displaying first two retrieved data of the NSArray because the number of rows are two in records array. but i want to set the numberOfRowsInsection will be according to the total number of attribute value retrieved by NSArray.
I have got the problem and I know the problem is here:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"The number of row in the object array: %d ",[records count]);
return [records count];
}
How can I fix it?
#pragma mark tableview
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
int sectionCount = [records count];
NSLog(#"section cout: %d",sectionCount);
return sectionCount;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:15.0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrow.png"]];
cell.accessoryView = imageView;
cell.accessoryType = UITableViewCellSelectionStyleNone;
tableView.separatorColor = [UIColor clearColor];
tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
cellView = [[[UIView alloc] initWithFrame:CGRectMake(5,8,290, 120)] autorelease];
cellView.backgroundColor = [UIColor clearColor];
cellView.tag =10;
[cell.contentView addSubview:cellView];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(2, 40, 48, 48)];
imgView.image = [UIImage imageNamed:#"productbox.png"];
imgView.layer.borderColor = [UIColor blackColor].CGColor;
imgView.layer.borderWidth = 2.0;
imgView.tag = 5;
[cellView addSubview:imgView];
CGRect idLabelRect = CGRectMake(65, 0, 190, 18);
idLabel = [[[UILabel alloc] initWithFrame:idLabelRect] autorelease];
idLabel.textAlignment = UITextAlignmentLeft;
idLabel.textColor = [UIColor blackColor];
idLabel.font = [UIFont systemFontOfSize:12];
idLabel.backgroundColor = [UIColor clearColor];
idLabel.layer.borderColor = [UIColor grayColor].CGColor;
idLabel.tag = 0;
CGRect statusRect = CGRectMake(65, 22, 190, 22);
statusLabel = [[[UILabel alloc] initWithFrame:statusRect] autorelease];
statusLabel.textAlignment = UITextAlignmentLeft;
statusLabel.textColor = [UIColor blackColor];
statusLabel.font = [UIFont systemFontOfSize:12];
statusLabel.backgroundColor = [UIColor clearColor];
statusLabel.layer.borderColor = [UIColor grayColor].CGColor;
statusLabel.tag = 1;
CGRect orderDateRect = CGRectMake(65, 48, 190, 22);
orderDate = [[[UILabel alloc] initWithFrame:orderDateRect] autorelease];
orderDate.textAlignment = UITextAlignmentLeft;
orderDate.textColor = [UIColor blackColor];
orderDate.font = [UIFont systemFontOfSize:12];
orderDate.backgroundColor = [UIColor clearColor];
orderDate.layer.borderColor = [UIColor grayColor].CGColor;
orderDate.tag = 2;
CGRect byRect = CGRectMake(65, 75, 190, 22);
byLabel = [[[UILabel alloc] initWithFrame:byRect] autorelease];
byLabel.textAlignment = UITextAlignmentLeft;
byLabel.textColor = [UIColor blackColor];
byLabel.font = [UIFont systemFontOfSize:12];
byLabel.backgroundColor = [UIColor clearColor];
byLabel.layer.borderColor = [UIColor grayColor].CGColor;
byLabel.tag = 3;
CGRect totalRect = CGRectMake(65, 98, 190, 22);
totalLabel = [[[UILabel alloc] initWithFrame:totalRect] autorelease];
totalLabel.textAlignment = UITextAlignmentLeft;
totalLabel.textColor = [UIColor blackColor];
totalLabel.font = [UIFont systemFontOfSize:12];
totalLabel.backgroundColor = [UIColor clearColor];
totalLabel.layer.borderColor = [UIColor grayColor].CGColor;
totalLabel.tag = 4;
[cellView addSubview:idLabel];
[cellView addSubview:statusLabel];
[cellView addSubview:orderDate];
[cellView addSubview:byLabel];
[cellView addSubview:totalLabel];
}
cellView = (UIView *)[cell.contentView viewWithTag:10];
idLabel = (UILabel *)[cellView viewWithTag:0];
statusLabel = (UILabel *)[cellView viewWithTag:1];
orderDate = (UILabel *)[cellView viewWithTag:2];
byLabel = (UILabel *)[cellView viewWithTag:3];
totalLabel = (UILabel *)[cellView viewWithTag:4];
imgView = (UIImageView *)[cellView viewWithTag:5];
idLabel.text = [NSString stringWithFormat:#"Order Id: %#",[[records objectAtIndex:indexPath.section] objectAtIndex:0]];
statusLabel.text = [NSString stringWithFormat:#"Status: %#",[[records objectAtIndex:indexPath.section] objectAtIndex:1]];
orderDate.text = [NSString stringWithFormat:#"Date: %#",[[records objectAtIndex:indexPath.section] objectAtIndex:2]];
byLabel.text =[NSString stringWithFormat:#"By: %#",[[records objectAtIndex:indexPath.section] objectAtIndex:3]];
totalLabel.text =[NSString stringWithFormat:#"Total: %#",[[records objectAtIndex:indexPath.section] objectAtIndex:4]];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Get the selected country
NSString *selectedSection = [ NSString stringWithFormat:#"%#",[[records objectAtIndex:indexPath.section] objectAtIndex:0] ];
dvController = [[OrderDetailsViewController alloc] initWithNibNameAndCurrentTweetUser:#"OrderDetailsViewController" bundle:nil:selectedSection];
[self.navigationController pushViewController:dvController animated:YES];
[dvController release];
dvController = nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 130;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 20)];
[v setBackgroundColor:[UIColor blackColor]];
UILabel* hdr = [[[UILabel alloc] initWithFrame:CGRectMake(10,0, tableView.bounds.size.width,20)] autorelease];
hdr.textAlignment = UITextAlignmentLeft;
hdr.font = [UIFont fontWithName:#"Arial-BoldMT" size:12];
hdr.textColor = [UIColor whiteColor];
hdr.backgroundColor = [UIColor blackColor];
[v addSubview:hdr];
hdr.text = [NSString stringWithFormat:#"Order #%#",[[records objectAtIndex:section] objectAtIndex:0]];
return v;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 20;
}
There are two ways to approach this problem.
The right way would be to take a look at this TBXML tutorial regarding parsing. This shows you what to do to parse each of the attributes out of each ProductData element entry.
The brute force method (which isn't one that I would do) would be to parse through your "records" array, which looks like this:
#"<id>1</id>",#"<productNumber>a91cc0f4c7</productNumber>",#"<name>Product 1</name>",#"<seoTitle>product-1</seoTitle>",#"<viewCount>0</viewCount>",
#"<availableStock>100.0</availableStock>",#"<lowStock>0.0</lowStock>",#"<image>5e928bbae358c93caedf6115fa7d178b.jpg</image>",
#"<basePrice>10.0</basePrice>",#"<costPrice>0.0</costPrice>",#"<height>1.0</height>",#"<width>1.0</width>",#"<depth>1.0</depth>",#"<weight>2.0</weight>"
and so on via this fast enumeration
for(NSString * elementText in records)
{
NSLog( #"%#", elementText );
// and search for "<" and ">" and strip out the name and the value using
// substring
}

Resources