tableView not reusing cell properly - iphone

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...

Related

Custom UITableViewCell with dynamic content

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.

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.

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.

Empty Table with no data display

I having problem with my table. After loading everything. My data is being loaded and string into name and loadscore. However it will not show in the table. Please help.
static const NSInteger kNameLabelTag = 1337;
static const NSInteger kScoreLabelTag = 5555;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UILabel *nameLabel = [[UILabel new] autorelease];
[nameLabel setTag:kNameLabelTag];
[cell.contentView addSubview:nameLabel];
UILabel *highscoreLabel = [[UILabel new] autorelease];
[highscoreLabel setTag:kScoreLabelTag];
[cell.contentView addSubview:highscoreLabel];
}
// Configure the cell.
//cell.textLabel.text = [loadhighScore objectAtIndex:indexPath.row];
NSDictionary *score = [self.loadhighScore objectAtIndex:indexPath.row];
NSString *name = [score objectForKey:#"ScoreName"];
NSString *loadscore = [score objectForKey:#"HighScore"];
[(UILabel *)[cell.contentView viewWithTag:kNameLabelTag] setText:name];
[(UILabel *)[cell.contentView viewWithTag:kScoreLabelTag] setText:loadscore];
return cell;
}
Do you have the tableview delegate and datasource connected to your class?
if you are loading in this data after the view has appeared on screen check that you have reloaded the tables data source [yourTableView reloadData];

UITableViewCell not appearing/reusing correctly from NIB

I have created a custom UITableViewCell from a NIB. Everything appears when the rowHeight is not set (albeit, everything is squished). I am not sure if I am reusing and creating the cells properly:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"ARCell";
ARObject *myARObject;
myARObject = [items objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"ARCell" owner:self options:nil];
cell = arCell;
self.arCell = nil;
}
UILabel *label;
label = (UILabel *)[cell viewWithTag:0];
label.text = [NSString stringWithFormat:#"%#", myARObject.username];
label = (UILabel *)[cell viewWithTag:1];
label.text = [NSString stringWithFormat:#"%#", myARObject.created_at];
label = (UILabel *)[cell viewWithTag:2];
label.text = [NSString stringWithFormat:#"%#", myARObject.articleTitle];
label = (UILabel *)[cell viewWithTag:3];
label.text = [NSString stringWithFormat:#"%#", myARObject.intro_text];
return cell;
}
- (CGFloat)tableView:(UITableView *)tblView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ CGFloat rowHeight = 105;
return rowHeight;
}
Problems:
Not all labels appear when rowHeight is set. If rowHeight isn't set, labels are squished
When rowHeight is not set, selecting an item shows all of the labels
Remove the else clause
You call loadNibNamed, but don't store result anywhere! Can't understand why your code works at all... Anyway, writing blind I would try something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"ARCell";
ARObject *myARObject = [items objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ARCell" owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
}
UILabel *label;
label = (UILabel *)[cell viewWithTag:0];
label.text = [NSString stringWithFormat:#"%#", myARObject.username];
label = (UILabel *)[cell viewWithTag:1];
label.text = [NSString stringWithFormat:#"%#", myARObject.created_at];
label = (UILabel *)[cell viewWithTag:2];
label.text = [NSString stringWithFormat:#"%#", myARObject.articleTitle];
label = (UILabel *)[cell viewWithTag:3];
label.text = [NSString stringWithFormat:#"%#", myARObject.intro_text];
return cell;
}
- (CGFloat)tableView:(UITableView *)tblView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 105.0;
}