PDA

View Full Version : Yet Another UITableViewCell Question...




DaveGee
Jul 31, 2008, 05:51 PM
Here is the problem... I have a UITableView that seems to behave strangely... Here is an example...

Using *this* as my "cellForRowAtIndexPath" performs flawlessly each and every time... I can scroll up scroll down click and hold... etc etc etc and everything I do the table behaves as it should...


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
if (cell == nil) {
cell = [[[UICellImageRight alloc] initWithFrame:CGRectZero reuseIdentifier:@"MyIdentifier"] autorelease];
}
ISY_26AppDelegate *appController = (ISY_26AppDelegate *)[[UIApplication sharedApplication] delegate];
NSDictionary *itemAtIndex = (NSDictionary *)[appController objectInListAtIndex:indexPath.row];
cell.text = [itemAtIndex objectForKey:@"DeviceName"];

return cell;
}


I wanted to try and do something a little more fancy and have a single cell have 2 lines with different fonts on each line... (compile the FINAL example in the TableViewSuite example code for an example of what I'm trying to shoot for...)

Instead of doing everything the authors of TableViewSuite did.. I wanted to make mine with less code so I tried the following... Using 2 UILabel's with different rects for the 'top line' and the 'lower line' of the cell.

Here is my new code....


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
if (cell == nil) {
cell = [[[UICellImageRight alloc] initWithFrame:CGRectZero reuseIdentifier:@"MyIdentifier"] autorelease];
}
ISY_26AppDelegate *appController = (ISY_26AppDelegate *)[[UIApplication sharedApplication] delegate];
NSDictionary *itemAtIndex = (NSDictionary *)[appController objectInListAtIndex:indexPath.row];

CGRect contentRect = CGRectMake(8.0, 4.0, 260, 20);
UILabel *textView = [[UILabel alloc] initWithFrame:contentRect];

textView.text = [itemAtIndex objectForKey:@"DeviceName"]; // [NSString stringWithFormat:@"%@",[itemAtIndex objectForKey:@"DeviceName"]];
textView.textColor = [UIColor blackColor];
textView.font = [UIFont boldSystemFontOfSize:14];
[cell.contentView addSubview:textView];
[textView release];

CGRect contentRect2 = CGRectMake(8.0, 20.0, 260, 20);
UILabel *textView2 = [[UILabel alloc] initWithFrame:contentRect2];

textView2.text = [itemAtIndex objectForKey:@"DeviceTypeName"]; // [NSString stringWithFormat:@"%@",[itemAtIndex objectForKey:@"DeviceTypeName"]];
textView2.textColor = [UIColor grayColor];
textView2.font = [UIFont systemFontOfSize:12];
[cell.contentView addSubview:textView2];
[textView2 release];

return cell;
}


Now it draws just like I wanted it to... Looks pretty good to me UNTIL I try to scroll the tableview and then CLICK AND HOLD a single cell...

What I should get is a cell with the text (FOR THAT CELL) and a blue highlight bar - indicating that I'm clicking down on the cell...

What I get instead is the blue bar BUT the text on both the top and bottom buttons look like they have 3 or 4 different labels all thrown one on top of each other...

For example...

=======
Apple
red
=======
Bananna
yellow
=======
Grape
green
=======

(this list would be long enough to scroll up and down but for this example I'll stop here)

Now when I click down on Banana/yellow I'd see Apple written below/above (?) and maybe even Grape written below/above (?)... Can't really tell the order of who is on top but it looks like a mess of text...

Oh yea the same thing happens to the text (on line 2 -- in the smaller font).. Clicking on Banana/yellow yellow to gets mashed with green and maybe even red.. It's hard to tell how much text is layered on top of each other but needless to say I'm doing something very wrong?

Oh and I even tried to 'rem out' all of the 2nd UILabel thinking I had some problem with my rects but all that happened was that I only got a single line in each cell (instead of two) but the layering text over text over text still happened...

Finally -- I just tried this now... If I just go to the first line and click and hold everything looks okay.. no text on top of text on top of text... once I scroll up and down (the list is bigger than the screen) **THEN** the problem shows up!

One more thing... I've tried this both ways once where I would issue the [textView release] and [textView2 release] and once where I didn't.... I couldn't tell any difference.. both ways had this problem..... I should be doing a release after the [cell.contentView addSubview:textView2] has been performed correct?

Any ideas??

Dave

P.S.

Since a pict is worth a thousand words....

Before...

http://www.garaffa.com/error0.png

Scroll up and then scroll down then up again... then click down on a cell:

After...

http://www.garaffa.com/error1.png

Oh and they don't STAY like that... once I release the mouse button (in the simulator) or remove my finger on my iPod the cell returns to normal... after a half-second or so..



DaveGee
Jul 31, 2008, 10:24 PM
Solution to problem:


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"MyIdentifier"] autorelease];
}
//
// This code below fixed the problem...
//
NSArray *subviews = [[NSArray alloc] initWithArray:cell.contentView.subviews];
for (UIView *subview in subviews) {
[subview removeFromSuperview];
}
[subviews release];
//
// Now you can continue creating the cell...
//
.
..
...


Need to 'clean out the previous subviews' before drawing the next cell.

Dave

DaveGee
Aug 2, 2008, 10:41 AM
Okay I realize I'm the only person contributing to this thread but someone sent me a PM thanking me for showing a fix for this problem I wanted to make sure the CORRECT fix was posted here as well...

What I posted above (while it will solve the problem) is *not* really the correct way to address this issue... Since all its doing is totally removing everything that was defined in cell only to replace it with MOSTLY everything that had been in there before...

Here is the correct fix...

I was have the same jumbled text problem on my table cells. I was driving me nuts. Many thanks to you for posting your own solution.

Well I'm glad it helped but I later found that it is not the BEST solution.. Especially if you have lots of rows...

The best solution is to 'almost fully construct' the 'table view cell' inside the if (cell == nil) {} statement and then only change the label.text and cell.text info outside the if (cell == nil) {} statement.

Here is a really simple example...


if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"MyIdentifier"] autorelease];
CGRect contentRect = CGRectMake(28.0f, 4.0f, 260.0f, 20.0f);
UILabel *textView = [[UILabel alloc] initWithFrame:contentRect];

textView.textColor = [UIColor blackColor];
textView.font = [UIFont boldSystemFontOfSize:15];
textView.tag = 1;
[cell.contentView addSubview:textView];
[textView release];

CGRect contentRect2 = CGRectMake(28.0f, 24.0f, 260.0f, 18.0f);
UILabel *textView2 = [[UILabel alloc] initWithFrame:contentRect2];

textView2.textColor = [UIColor grayColor];
textView2.font = [UIFont systemFontOfSize:12];
textView2.tag = 2;
[cell.contentView addSubview:textView2];
[textView2 release];
}


The code above puts TWO labels inside a single cell but it only does it once no matter how many rows long your tableview happens to be.... Notice how the code does NOT say what the actual labels should say.. Its not supposed to... the place where you define what the label.text actually says is found **below** the code you see above.

Now BELOW that code you put the following....


UILabel *txtView = (UILabel*)[cell viewWithTag:1];
UILabel *txtView2 = (UILabel*)[cell viewWithTag:2];
txtView.text = [itemAtIndex objectForKey:@"DeviceName"];
objectForKey:@"DeviceName"]]; // Whatever you want the label to say
txtView2.text = [NSString stringWithFormat:@"%@",[itemAtIndex objectForKey:@"DeviceTypeName"]]; // Whatever you want the other label to say
return cell;


I hope this makes sense... because its actually the *right way* to do this stuff and it will keep your tables using less memory and also scroll faster taboot!

Dave

pete42
Oct 19, 2010, 10:45 PM
Thanks. I've had this problem for a long time. usually fixing it by adding a view behind the labels.

this way is genius and is clearly the right way.