Custom UITableViewCell with dynamic content - iphone

I'm trying to create a UITableView which loads a custom cell from a XIB. I have EventsCell.xib along with the .m and .h files.
The cell's content and height are dynamic, as it can contain an unknown number of subviews.
This is the code that loads the cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EventsCellIdentifier";
EventsCell *cell = (EventsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"EventsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *hour = [[[eventsArray objectAtIndex:[indexPath section]] valueForKey:#"hours"] objectAtIndex:[indexPath row]];
NSArray *events = [hour valueForKey:#"events"];
cell.events = events;
cell.timeLabel.text = [hour valueForKey:#"name"];
int offset = 0;
for(NSDictionary *event in events)
{
UIView *vvv = [[UIView alloc] initWithFrame:CGRectMake(50, offset, 270, 44)];
[vvv setBackgroundColor:[UIColor clearColor]];
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 44)];
lab.text = [event valueForKey:#"name"];
lab.backgroundColor = [UIColor clearColor];
[vvv addSubview:lab];
[cell.contentView addSubview:vvv];
offset += 44;
}
return cell;
}
It loads the cells, but after i scroll a few times on the table view, the content looks like this:
What am i doing wrong?..
Thank you!
==================== UPDATE ====================
Now another thing is happening.
I've added all of the elements of the subviews i add to the cell in a separate view controller. Like bellow.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EventsCellIdentifier";
EventsCell *cell = (EventsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"EventsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
for (UIView *subV in [cell.contentView subviews]){
[subV removeFromSuperview];
}
NSDictionary *hour = [[[eventsArray objectAtIndex:[indexPath section]] valueForKey:#"hours"] objectAtIndex:[indexPath row]];
NSArray *events = [hour valueForKey:#"events"];
cell.events = events;
cell.timeLabel.text = [hour valueForKey:#"name"];
int offset = 0;
for(NSDictionary *event in events)
{
EventBoxViewController *ebvc = [[EventBoxViewController alloc] initWithNibName:#"EventBoxViewController" bundle:nil];
ebvc.nameLabel.text = [event valueForKey:#"name"];
[ebvc.view setFrame:CGRectMake(50, offset, 270, 44)];
[cell.contentView addSubview:ebvc.view];
offset += 44;
}
return cell;
}
And they don't load as they should. Please see the image below.
They load only when i scroll through the cells and even then they don't load as they should.
Also the text for the label does not get assigned.
Any ideas on what i am doing wrong?
Thank you.

Views are added on cell.contentView, Since the cells are reuable it still remains added,
If we remove all the subViews it will work
for (UIView *subV in [cell.contentView subviews]){
[subV removeFromSuperview];
}
Add the above code after
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"EventsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}

It works if you add a UIVIew* to your table cell prototype and clear it's sub-views.
like this:
UIView* editView = (UIView*)[cell viewWithTag:102];
for (UIView *subV in [editView subviews]){
[subV removeFromSuperview];

More readable solution is instead of dequeueing a cell, to create one every time, but it depends how many of them you need to load in the end because of overhead. This removing thing looks nasty.

Related

custom label value is disappearing when scrolling table view

I am new to iphone. my cutomcell label value is disappearing when I scroll the table view.
Again it appears when I click on that cell.
Can anyone help me?
Thanks in Advance.
//table view in view controller created in xib
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ListOfProductsCell";
ListOfProductsCell *cell = (ListOfProductsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
NSArray *nib =[[NSBundle mainBundle] loadNibNamed:#"ListOfProductsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
productItemDit=[productListArry objectAtIndex:indexPath.row];
NSString *offerStr= [NSString stringWithFormat:#"%.2f",[[productItemDit objectForKey:#"offer"] floatValue]];
NSString *fullCostStr=[[currencyCodeStr stringByAppendingString:#" "] stringByAppendingString:offerStr];
NSLog(#"%#",fullCostStr);
cell.itemCostLbl.text=fullCostStr;
} else {
cell.itemStepper = (UIStepper *) [cell viewWithTag:2];
cell.itemAddedLbl =(UILabel*)[cell viewWithTag:1];
}
if (tableView == self.searchDisplayProduct.searchResultsTableView) {
searchProductItemDit=[searchProductListArry objectAtIndex:indexPath.row];
NSLog(#"searchdit:%#",searchProductItemDit);
cell.itemNameLbl.text= [searchProductItemDit objectForKey:#"name"];
self.searchDisplayProduct.searchResultsTableView.separatorColor=[UIColor colorWithRed:200.0 green:0.0 blue:0.0 alpha:1.0];
} else {
productItemDit=[productListArry objectAtIndex:indexPath.row];
NSLog(#"dit:%#",productItemDit);
cell.itemNameLbl.text=[productItemDit objectForKey:#"name"];
}
cell.itemAddedLbl.text = [[NSString alloc] initWithFormat:#"%d",itemCount];
cell.itemImg.image = [UIImage imageNamed:#"profp.jpg"];
return cell;
}
Solved by doing like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ListOfProductsCell";
ListOfProductsCell *cell = (ListOfProductsCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
NSArray *nib =[[NSBundle mainBundle] loadNibNamed:#"ListOfProductsCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
} else {
cell.itemStepper = (UIStepper *) [cell viewWithTag:2];
cell.itemAddedLbl =(UILabel*)[cell viewWithTag:1];
}
if (tableView == self.searchDisplayProduct.searchResultsTableView) {
cell.itemNameLbl.text= [[searchProductListArry objectAtIndex:indexPath.row] objectForKey:#"name"];
} else {
cell.itemNameLbl.text=[[productListArry objectAtIndex:indexPath.row] objectForKey:#"name"];
}
cell.itemCostLbl.text=[NSString stringWithFormat:#"%# %.2f", currencyCodeStr , [[[productListArry objectAtIndex:indexPath.row] objectForKey:#"offer"] floatValue]];
cell.itemAddedLbl.text = [[NSString alloc] initWithFormat:#"%d",itemCount];
cell.itemImg.image = [UIImage imageNamed:#"profp.jpg"];
return cell;
}
As you haven't post much of the information this is my guess.when you scroll table view it internally calls the reloadData method . You need to use reuse Identifier to preserve the state of the cell. You can initialize the cell in cellForRowAtIndexPath like :
static NSString *cellIdentifier = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
// or cell initializing logic here for the custom cell
}
in case of custom cell add reuse identifier in the xib and use it in your cellForRowAtIndexPath method

tableView not reusing cell properly

This is my code for a tableView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CounterCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"CounterCell" owner:self options:nil];
cell = nibLoadedCell2;
}
Program *program = [memory getProgramAtIndex:[memory chosenProgram]];
NSMutableArray *arrayOfIntervals = [[NSMutableArray alloc] init];
arrayOfIntervals = program.arrayOfIntervals;
NSMutableDictionary *interval = [arrayOfIntervals objectAtIndex:indexPath.row];
UITextField *intervalName = (UITextField *)[cell viewWithTag:1];
intervalName.text = [interval objectForKey:#"nameOfInterval"];
[intervalName addTarget:self action:#selector(returnKey:) forControlEvents:UIControlEventEditingDidEndOnExit];
[intervalName addTarget:self action:#selector(editingEnded:) forControlEvents:UIControlEventEditingDidEnd];
[intervalName addTarget:self action:#selector(editTextField:) forControlEvents:UIControlEventEditingDidBegin];
timeInSeconds = [[interval objectForKey:#"timeInSeconds"] intValue];
if (indexPath.row == 0) {
firstCellGeneralTime = timeInSeconds;
}
NSString *time = [self timeTextWithTimeInSeconds:timeInSeconds];
UILabel *intervalTime = (UILabel *)[cell viewWithTag:2];
intervalTime.text = time;
if (indexPath.row == 0) {
majorLabel.text = time;
}
UILabel *hourString = (UILabel *)[cell viewWithTag:11];
hourString.text = [NSString stringWithFormat:#"%d",hoursInt];
UILabel *minuteString = (UILabel *)[cell viewWithTag:12];
minuteString.text = [NSString stringWithFormat:#"%d",minutesInt];
UILabel *secondString = (UILabel *)[cell viewWithTag:13];
secondString.text = [NSString stringWithFormat:#"%d",secondsInt];
UIButton *editTime = (UIButton *)[cell viewWithTag:21];
[editTime addTarget:self action:#selector(openPicker:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
My table view shows a bit less than 3 cells, and on a certain point i delete the first cell and than the 4th cell is showing up.
The problem is that the 4th cell is exactly like my 3rd cell, although it should be different.
It does reuse it as it should.
I don't know what i've done wrong.
This is the code for the deletion of a cell:
NSIndexPath *firstCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
NSArray *arrayOfIndexPath = [[NSArray alloc] initWithObjects:firstCellIndexPath, nil];
[atableView deleteRowsAtIndexPaths:arrayOfIndexPath withRowAnimation:UITableViewRowAnimationTop];
You have to remove the first interval from the program.arrayOfIntervals array while deleting the cell.
Found it, the problematic code is:
Program *program = [memory getProgramAtIndex:[memory chosenProgram]];
NSMutableArray *arrayOfIntervals = [[NSMutableArray alloc] init];
arrayOfIntervals = program.arrayOfIntervals;
NSMutableDictionary *interval = [arrayOfIntervals objectAtIndex:indexPath.row];
I am creating a new program and get the details of the intervals from it, instead of using the program i removed the first interval from…
I feel so dumb...

iPhone/iPad : table view scroll crash in ipad

Hi all I want to show more than 120 images in tableview its runs fine in simulator but crash in device (ipad).
logs show memory warning but I am releasing perfectly I don't know why I get this message and crash. Images comes from server I am using following code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
FullTableViewCell *cell = (FullTableViewCell *)
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle]
loadNibNamed:#"FullTableViewCell" owner:nil options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[UITableViewCell class]]) {
cell = (FullTableViewCell *)currentObject;
break;
}
}
}
NSDictionary *dic = [socketConnection().imageInfoArray objectAtIndex:indexPath.row];
int imageId = [[dic objectForKey:#"id"] intValue];
UIImage *image = [socketConnection().serverImageArray objectAtIndex:indexPath.row];
UIImage *IMMage = [self scaleImage:image toResolution:740];
cell.cellIMage.image = IMMage;
cell.addButton.tag = imageId;
cell.zoomOutButton.tag = imageId;
[cell.zoomOutButton addTarget:self action:#selector(_ZoomOut:) forControlEvents:UIControlEventTouchUpInside];
[cell.addButton addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
cell.transform = CGAffineTransformMakeRotation(3.14159265+(3.14159265/2));
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
plz anybody help me where i am wrong..
Implement:
if (cell) {
[cell setImage:nil];
[cell setImage://image];
// Put ALL cell code here
}
and release:
image and IMMage and FullTableView and topLevelObjects and dic before
return cell;
AND FINALLY AND MOST IMPORTANTLY:
also analyze you're project to see for leaks

Why aren't my NSMutableArray objects being added to the UITableView straight away?

I have an NSMutableArray with objects within it and I use the following code to add/remove objects from the UITableView. It works but only after closing and relaunching the app, not straight away. Why is this? Here is my code (maincelltext is the title in the cell and subtitlecelltext is the subtitle):
maincelltext = [[NSMutableArray alloc] init];
subtitlecelltext = [[NSMutableArray alloc] init];
[maincelltext addObject:#"TITLE"];
[subtitlecelltext addObject:#"SUBTITLE TEST"];
EDIT: Here is my UITableView code:
- (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];
}
cell.textLabel.font = [UIFont fontWithName:#"HelveticaBold" size:16.0];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.numberOfLines = 1;
// Configure the cell.
UIImage *cellImage = [UIImage imageNamed:#"warning.png"];
CGRect cropRect = CGRectMake(0.0, 0.0, 12.0, 12.0);
CGImageRef croppedImage = CGImageCreateWithImageInRect([cellImage CGImage], CGRectMake(0.0f,0.0f,cellImage.size.width,cellImage.size.height));
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:cropRect];
[myImageView setImage:[UIImage imageWithCGImage:croppedImage]];
CGImageRelease(croppedImage);
[self.view addSubview:myImageView];
cell.imageView.image = cellImage;
NSString *subjectString = [maincelltext objectAtIndex: [indexPath row]];
cell.textLabel.text = subjectString;
NSString *subtitle = [subtitlecelltext objectAtIndex: [indexPath row]];
cell.detailTextLabel.text = subtitle;
if(maincelltext.count == 0){
NSString *notabledata = [NSString stringWithFormat:#"No Dates Set"];
[maincelltext addObject:notabledata];
}
return cell;
}
Thanks!
you need to tell the UITableView that it needs to insert the rows. First determine the index in the array the new object(s) are now at, then tell the UITableView to insert the rows like this:
NSIndexPath *indexPathOfNewObject=[NSIndexPath indexPathForRow: newObjectIndex section:0];
NSArray *indexPathArray=[NSArray arrayWithObject: indexPathOfNewObject];
[self.tableView beginUpdates];
// Note that UITableViewRowAnimationAutomatic is for iOS5 only.
[self.tableView insertRowsAtIndexPaths: indexPathArray withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
by using this method, you will get the cool animation effect on the tableView.
Alternatively, you could just call [self.tableView reloadData] and it will just reload all the data.
Good luck!
Just do a [myTableView reloadData]; after you did an [myArray addObject:myObject]; and you should be fine.

Why my UITableView not smooth when scroll first time?

My table view cell has four labels.
The table view is not smooth when scroll in first time. After all cells displayed one time, the scrolling is so smooth with no problem.
So I thought the problem is the speed of loading one cell in the first time.
I have reuse cell but the problem is not solved. Please help me! Thanks so much!
Here is my code:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"ForumListTableViewCell" owner:self options:nil];
cell = [views objectAtIndex:0];
}
NSDictionary *cate = [_forums objectAtIndex:indexPath.section];
NSArray *forumsInCate = [cate objectForKey:#"forums"];
NSDictionary *forumInfo = [forumsInCate objectAtIndex:indexPath.row];
// title1
UILabel *forumTitleLabel = (UILabel *)[cell viewWithTag:1];
forumTitleLabel.text = [forumInfo objectForKey:#"name"];
// master
UILabel *masterLabel = (UILabel *)[cell viewWithTag:2];
NSString *master = [forumInfo objectForKey:#"moderators"];
masterLabel.text = master;
// title2
UILabel *threadTitleLabel = (UILabel *)[cell viewWithTag:3];
NSString *lastPostTitle;
NSDictionary *lastPostInfo = [forumInfo objectForKey:#"lastpost"];
lastPostTitle = [lastPostInfo objectForKey:#"subject"];
threadTitleLabel.text = lastPostTitle;
// author
UILabel *authorLabel = (UILabel *)[cell viewWithTag:4];
authorLabel.text = [NSString stringWithFormat:#"%# / %#",
[forumInfo objectForKey:#"threads"],
[forumInfo objectForKey:#"posts"]
];
return cell;
}
NSArray *views = [[NSBundle mainBundle] loadNibNamed:#"ForumListTableViewCell" owner:self options:nil];
on .h
NSArray *views;
on .m
-(void)viewDidLoad
{
[super viewDidLoad];
views = [[NSBundle mainBundle] loadNibNamed:#"ForumListTableViewCell" owner:self options:nil];
}
- (void)dealloc
{
//--- other object ----
[views release];
[super dealloc];
}