Presence 2 - multiline text problem

39 views
Skip to first unread message

Russell

unread,
May 3, 2009, 2:34:49 PM5/3/09
to iphone-appd...@googlegroups.com
Up to now, I have been able to figure out every assignment. I am really stuck this time. Only part of the status message shows, and the text goes closer to the edge of the window than it should: http://img24.imageshack.us/img24/6924/picture6qaj.png I had some issues with using tableView.width (undefined method), which was shown in lecture 8. Here is the important code for this table: -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *message = [[person statusMessages] objectAtIndex:indexPath.row]; CGSize size = [message sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(300.0, 1000.0) lineBreakMode:UILineBreakModeTailTruncation]; return(size.height + 20); } // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; } UILabel *statusMessage = [[UILabel alloc] initWithFrame:cell.contentView.bounds]; NSLog([[person statusMessages] objectAtIndex:indexPath.row]); [statusMessage setNumberOfLines:0]; [statusMessage setLineBreakMode:UILineBreakModeWordWrap]; [statusMessage setText:[[person statusMessages] objectAtIndex:indexPath.row]]; [cell.contentView addSubview:statusMessage]; [statusMessage release]; return cell; } Please help me, I am not quite sure what I am doing!

Rich MacDonald

unread,
May 3, 2009, 4:47:48 PM5/3/09
to iphone-appd...@googlegroups.com
On Sun, May 3, 2009 at 11:34 AM, Russell <skii...@gmail.com> wrote:
tableView.width

This was a typo (or simplification) in the slides.  You'd need to access the bounds or frame property to get at the width:

tableView.bounds.size.width

When you calculate the size of the label, don't forget that you have a pair of 10 pixel insets on both the left and right side (i.e. tableView.bounds.size.width - 4 * 10).  

On a slight tangent, I like the property accessor dot-syntax for the most part, but it can get confusing when mixed with structure dot-syntax.  You'd think you could say something like:

statusLabel.frame.size.width = 280;

But this results in an error: invalid lvalue in assignment
This works instead:

CGRect statusFrame = statusLabel.frame;

statusFrame.size.width = 280;

statusLabel.frame  = statusFrame;


I think what is happening in the error case is that the frame property getter, rather than setter, is called when other dot components follow.  If it were nested properties, all but the last component would have getters called and the last component, for an lvalue, would have the setter called.  


-Rich

WBSKI

unread,
May 3, 2009, 6:26:50 PM5/3/09
to iPhone Application Development Auditors
Hi Rich,

Thanks for the help!

There is still one problem though.

The UITableViewCell is just the regular height of a cell, while the
visible height of the cell set in the heightForRow method is larger.
The text is getting cut off because of this. How can I get the
UITableViewCell to automatically fit itself to the row height?

Thanks so much!

On May 3, 1:47 pm, Rich MacDonald <rich.macdon...@gmail.com> wrote:
> On Sun, May 3, 2009 at 11:34 AM, Russell <skiinf...@gmail.com> wrote:
> > tableView.width
>
> This was a typo (or simplification) in the slides.  You'd need to access the
> bounds or frame property to get at the width:
>
> tableView.bounds.size.width
>
> When you calculate the size of the label, don't forget that you have a pair
> of 10 pixel insets on both the left and right side
> (i.e. tableView.bounds.size.width - 4 * 10).
>
> On a slight tangent, I like the property accessor dot-syntax for the most
> part, but it can get confusing when mixed with structure dot-syntax.  You'd
> think you could say something like:
>
> statusLabel.frame.size.width = 280;
>
> But this results in an error: invalid lvalue in assignment
> This works instead:
> *
> *
> *
>
> CGRect statusFrame = statusLabel.frame;
>
> statusFrame.size.width = 280;
>
> statusLabel.frame  = statusFrame;
>
> I think what is happening in the error case is that the frame property
> getter, rather than setter, is called when other dot components follow.  If
> it were nested properties, all but the last component would have getters
> called and the last component, for an lvalue, would have the setter called.
>
> -Rich
> *

Chris Schepman

unread,
May 3, 2009, 7:42:36 PM5/3/09
to iphone-appd...@googlegroups.com
I'm struggling with this right now as well. It's like you have to calculate the display height for the cell. Then you have to calculate the same thing inside cellForRowAtIndexPath and set the contentView to the right size as well. I don't think the contentView is being sized with the cell...

I'm not sure the cell is being sized either actually...it keeps coming in at a height of 44, even thought the heightForRowAtIndexPath is making the cells visibly much larger.

hmm...I'm going to keep tinkering and I'll post if I find something that works. :)

Rich MacDonald

unread,
May 4, 2009, 1:14:45 AM5/4/09
to iphone-appd...@googlegroups.com
I haven't figured out - or read in these threads - any solutions that don't involve making this height calculation twice or at least caching the height in an array for quicker look-up the second time.  This does seem a bit inefficient/inelegant, and I too would love to hear if there is a better solution.  

In regards to the tableView:cellForRowAtIndexPath:, we're creating the UITableViewCell ourselves so I hadn't put much stake in getting a useful height from that (i.e. what we calculated from tableView:heightForRowAtIndexPath: ).  The dequeueReusableCellWithIdentifier: UITableView method sounded like it might set the height for us, but it seems like it's just returning a cell with the values when it was added to the queue...definitely getting different heights than just 44 after scrolling back through the table.  

One possibility is to use

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath


which is a delegate method called after tableView:cellForRowAtIndexPath:   The cell passed here does indeed have the correct height for its frame, so you could alter the label height backwards from that.  But after doing this successfully, I'm not sure I like the solution for two reasons:

  1. It requires a similar amount of code to work backwards from the row height.  This seems no better than duplicating row height calculation code; and it is worse in that duplicating the code verbatim is only one thing to figure out instead of two.  
  2. It sounds like this delegate isn't intended for this kind of alteration (from Table View Programming Guide):  

The table view’s data source implementation of tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell. In addition, a table view sends a tableView:willDisplayCell:forRowAtIndexPath: message to its delegate just before it draws a row. If the delegate chooses to implement this method, it can customize the cell object before it is displayed. Note that the delegate in this method should change state-based properties set earlier by the table view, such as selection and background color, and not content.

So in the end, calculating the height once and caching it for later use may be the most efficient route.  Just have to make sure to invalidate the cache if needed (e.g. rotation change causing cell width resizing).  

-Rich

Chris Schepman

unread,
May 4, 2009, 3:27:04 AM5/4/09
to iphone-appd...@googlegroups.com
I just realized that ... 

statusLabel.text = [[person statuses] objectAtIndex:indexPath.row];

[statusLabel sizeToFit];


seems to work without having to make the calculation again. I suppose it's making it for us...still tinkering with the  cell reuse though.

Rich MacDonald

unread,
May 4, 2009, 4:47:30 AM5/4/09
to iphone-appd...@googlegroups.com
Interesting. Someone else suggested sizeToFit, and it sounded like their method relied on calculating the row height by duplicating the label setup code in there (i.e. As opposed to the NSString code from class).  

For whatever reason sizeToFit works 90% of the time for me, but with SHAQ and Shatner, a few label widths get shortened so that the wrapping results in more lines of text than the row height budgeted for.  Maybe in the act of reusing cells the width gets shortened on one or two of the cells and I need to reset it outside the cell creation code so it will work after reuse...

-Rich

Chris Schepman

unread,
May 4, 2009, 1:05:06 PM5/4/09
to iphone-appd...@googlegroups.com
When I enable cell reuse the same thing happens to me. The widths go shorter and the text runs off the screen. It doesn't happen for Woz as well. Weird.

So far I've been getting this stuff no problem, but I've spent a few days on this problem. I can't wait to understand it.

There must be way to get the width set correctly, but I'm bummed that -sizeToFit doesn't handle it. ;)

talltodd

unread,
May 4, 2009, 2:27:50 PM5/4/09
to iPhone Application Development Auditors
I did this and it helped some but not perfect:
frame.size.width = frame.size.width - 30;


On May 4, 1:05 pm, Chris Schepman <csc...@gmail.com> wrote:
> When I enable cell reuse the same thing happens to me. The widths go shorter
> and the text runs off the screen. It doesn't happen for Woz as well. Weird.
>
> So far I've been getting this stuff no problem, but I've spent a few days on
> this problem. I can't wait to understand it.
>
> There must be way to get the width set correctly, but I'm bummed that
> -sizeToFit doesn't handle it. ;)
>
> On Mon, May 4, 2009 at 1:47 AM, Rich MacDonald <rich.macdon...@gmail.com>wrote:
>
> > Interesting. Someone else suggested sizeToFit, and it sounded like their
> > method relied on calculating the row height by duplicating the label setup
> > code in there (i.e. As opposed to the NSString code from class).
>
> > For whatever reason sizeToFit works 90% of the time for me, but with SHAQ
> > and Shatner, a few label widths get shortened so that the wrapping results
> > in more lines of text than the row height budgeted for.  Maybe in the act of
> > reusing cells the width gets shortened on one or two of the cells and I need
> > to reset it outside the cell creation code so it will work after reuse...
>
> > -Rich
>
> > On May 4, 2009, at 12:27 AM, Chris Schepman <csc...@gmail.com> wrote:
>
> > I just realized that ...
>
> > statusLabel.text = [[person statuses] objectAtIndex:indexPath.row];
>
> > [statusLabel sizeToFit];
>
> > seems to work without having to make the calculation again. I suppose it's
> > making it for us...still tinkering with the  cell reuse though.
>
> > On Sun, May 3, 2009 at 10:14 PM, Rich MacDonald <<rich.macdon...@gmail.com>
> > rich.macdon...@gmail.com> wrote:
>
> >> I haven't figured out - or read in these threads - any solutions that
> >> don't involve making this height calculation twice or at least caching the
> >> height in an array for quicker look-up the second time.  This does seem a
> >> bit inefficient/inelegant, and I too would love to hear if there is a better
> >> solution.
>
> >> In regards to the tableView:cellForRowAtIndexPath:, we're creating the
> >> UITableViewCell ourselves so I hadn't put much stake in getting a useful
> >> height from that (i.e. what we calculated from
> >> tableView:heightForRowAtIndexPath: ).  The dequeueReusableCellWithIdentifier:
> >> UITableView method sounded like it might set the height for us, but it
> >> seems like it's just returning a cell with the values when it was added to
> >> the queue...definitely getting different heights than just 44 after
> >> scrolling back through the table.
>
> >> One possibility is to use
>
> >> - (void)tableView:(UITableView *)tableView
> >> willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath
> >> *)indexPath
>
> >> which is a delegate method called after tableView:cellForRowAtIndexPath:
> >> The cell passed here does indeed have the correct height for its frame, so
> >> you could alter the label height backwards from that.  But after doing this
> >> successfully, I'm not sure I like the solution for two reasons:
>
> >>    1. It requires a similar amount of code to work backwards from the row
> >>    height.  This seems no better than duplicating row height calculation code;
> >>    and it is worse in that duplicating the code verbatim is only one thing to
> >>    figure out instead of two.
> >>    2. It sounds like this delegate isn't intended for this kind of
> >>    alteration (from Table View Programming Guide):
>
> >> The table view’s data source implementation of
> >> tableView:cellForRowAtIndexPath: should *always* reset all content when
> >> reusing a cell. In addition, a table view sends a
> >> tableView:willDisplayCell:forRowAtIndexPath: message to its delegate just
> >> before it draws a row. If the delegate chooses to implement this method, it
> >> can customize the cell object before it is displayed. Note that the delegate
> >> in this method should change state-based properties set earlier by the table
> >> view, such as selection and background color, and not content.
>
> >> So in the end, calculating the height once and caching it for later use
> >> may be the most efficient route.  Just have to make sure to invalidate the
> >> cache if needed (e.g. rotation change causing cell width resizing).
>
> >> -Rich
>
> >> On Sun, May 3, 2009 at 4:42 PM, Chris Schepman < <csc...@gmail.com>
> >> csc...@gmail.com> wrote:
>
> >>> I'm struggling with this right now as well. It's like you have to
> >>> calculate the display height for the cell. Then you have to calculate the
> >>> same thing inside cellForRowAtIndexPath and set the contentView to the right
> >>> size as well. I don't think the contentView is being sized with the cell...
>
> >>> I'm not sure the cell is being sized either actually...it keeps coming in
> >>> at a height of 44, even thought the heightForRowAtIndexPath is making the
> >>> cells visibly much larger.
>
> >>> hmm...I'm going to keep tinkering and I'll post if I find something that
> >>> works. :)
>

WBSKI

unread,
May 4, 2009, 3:24:10 PM5/4/09
to iPhone Application Development Auditors
I can get it to work perfectly with this:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
(NSIndexPath *)indexPath {
NSString *message = [[person statusMessages]
objectAtIndex:indexPath.row];
CGSize size = [message sizeWithFont:[UIFont systemFontOfSize:16]
constrainedToSize:CGSizeMake(tableView.bounds.size.width - 4*10,
1000.0)
lineBreakMode:UILineBreakModeTailTruncation];
NSLog(@"Height %d",tableView.bounds.size.width);
return(size.height + 10);
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"VariableHeightCell";
UITableViewCell *cell = [[UITableViewCell alloc]
initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
UILabel *statusLabel = [[UILabel alloc]
initWithFrame:cell.contentView.bounds];

CGRect statusFrame = statusLabel.frame;
statusFrame.size.width = 280;
statusFrame.origin.x = 10;
statusFrame.origin.y = 5;
statusLabel.frame = statusFrame;
NSLog([[person statusMessages] objectAtIndex:indexPath.row]);
[statusLabel setNumberOfLines:0];
[statusLabel setLineBreakMode:UILineBreakModeTailTruncation];
[statusLabel setText:[[person statusMessages]
objectAtIndex:indexPath.row]];
[statusLabel setFont:[UIFont systemFontOfSize:16]];
[statusLabel sizeToFit];
NSLog([NSString
stringWithFormat:@"%d",cell.contentView.bounds.size.height]);
[cell.contentView addSubview:statusLabel];
[statusLabel release];
// Set up the cell...

return cell;
}

As soon as I turn cell reuse on though, there are rendering glitches
and overlapping text.

Rich MacDonald

unread,
May 4, 2009, 4:11:00 PM5/4/09
to iphone-appd...@googlegroups.com
Chris, thanks for your feedback.  I don't know if I would have caught this if you hadn't mentioned sizeToFit working but that you hadn't implemented cell reuse yet.  Your last update made it even more clear that reuse was the culprit.  

I've gotten sizeToFit to work now by not bothering to set the label frame when first creating it and instead setting the frame with appropriate width and arbitrary height just before calling size to fit:


statusLabel.frame = CGRectMake(CELL_PADDING, CELL_PADDING, statusLabelWidth, 20);

[statusLabel sizeToFit];

 
Where statusLabelWidth was calculated as: tableView.bounds.size.width - 4*CELL_PADDINGwith #define CELL_PADDING 10

Works like a charm on all the users tweets.  So it seems that resizeToFit would, understandably, change the frame width when it encountered short one-liners like SHAQ's "@tgoace got u" or "@jromulo great point".  Then when the cell was queued and subsequently dequeued the width remained at this reduced size, leading to our wrapping issues with too many lines.  

This also explains why saw no issues with Woz.  The only one-liner was at the bottom of the table view.  This made me think that a good final test to confirm this theory would be to scroll fully back up and down repeatedly to see if eventually a cell's rendering would get messed up when the resized width cell made it through the queue.  Took many repetitions, but eventually it did mess up the top cell:

Woz Messed Up.png 

Here's a composited image where the messed up row is put just above the last, one-liner row row with an added guide to compare their widths:

Woz Comp.png



The table view’s data source implementation of tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell. 

After dealing with this confusing behavior, I now understand why they emphasize this point; it's easy to think the content properties haven't changed, but it's easy to overlook state-change side effects.  

-Rich

WBSKI

unread,
May 4, 2009, 7:20:37 PM5/4/09
to iPhone Application Development Auditors
Still isn't working for me. Could you post your entire code for the
cellForRowAtIndexPath delegate method?

Thanks

On May 4, 1:11 pm, Rich MacDonald <rich.macdon...@gmail.com> wrote:
> Chris, thanks for your feedback.  I don't know if I would have caught this
> if you hadn't mentioned sizeToFit working but that you hadn't implemented
> cell reuse yet.  Your last update made it even more clear that reuse was the
> culprit.
> I've gotten sizeToFit to work now by not bothering to set the label frame
> when first creating it and instead setting the frame with appropriate width
> and arbitrary height just before calling size to fit:
>
> statusLabel.frame = CGRectMake(CELL_PADDING, CELL_PADDING, statusLabelWidth,
> 20);
>
> [statusLabel sizeToFit];
>
> Where statusLabelWidth was calculated as: tableView.bounds.size.width - 4*
> CELL_PADDING; with #define CELL_PADDING 10
>
> Works like a charm on all the users tweets.  So it seems that resizeToFit
> would, understandably, change the frame width when it encountered short
> one-liners like SHAQ's "@tgoace got u" or "@jromulo great point".  Then when
> the cell was queued and subsequently dequeued the width remained at this
> reduced size, leading to our wrapping issues with too many lines.
>
> This also explains why saw no issues with Woz.  The only one-liner was at
> the bottom of the table view.  This made me think that a good final test to
> confirm this theory would be to scroll fully back up and down repeatedly to
> see if eventually a cell's rendering would get messed up when the resized
> width cell made it through the queue.  Took many repetitions, but eventually
> it did mess up the top cell:
>
> [image: Woz Messed Up.png]
>
> Here's a composited image where the messed up row is put just above the
> last, one-liner row row with an added guide to compare their widths:
>
> [image: Woz Comp.png]
>
> From Table View Programming Guide for iPhone OS: A Closer Look at Table-View
> Cells<http://developer.apple.com/iphone/library/documentation/UserExperienc...>
> :
>
> The table view’s data source implementation of
> tableView:cellForRowAtIndexPath:<http://developer.apple.com/iphone/library/documentation/UIKit/Referen...>
>  should *always* reset all content when reusing a cell.
>
> After dealing with this confusing behavior, I now understand why they
> emphasize this point; it's easy to think the content properties haven't
> changed, but it's easy to overlook state-change side effects.
>
> -Rich
>
>
>
> On Mon, May 4, 2009 at 10:05 AM, Chris Schepman <csc...@gmail.com> wrote:
> > When I enable cell reuse the same thing happens to me. The widths go
> > shorter and the text runs off the screen. It doesn't happen for Woz as well.
> > Weird.
>
> > So far I've been getting this stuff no problem, but I've spent a few days
> > on this problem. I can't wait to understand it.
>
> > There must be way to get the width set correctly, but I'm bummed that
> > -sizeToFit doesn't handle it. ;)
>
> > On Mon, May 4, 2009 at 1:47 AM, Rich MacDonald <rich.macdon...@gmail.com>wrote:
>
> >> Interesting. Someone else suggested sizeToFit, and it sounded like their
> >> method relied on calculating the row height by duplicating the label setup
> >> code in there (i.e. As opposed to the NSString code from class).
>
> >> For whatever reason sizeToFit works 90% of the time for me, but with SHAQ
> >> and Shatner, a few label widths get shortened so that the wrapping results
> >> in more lines of text than the row height budgeted for.  Maybe in the act of
> >> reusing cells the width gets shortened on one or two of the cells and I need
> >> to reset it outside the cell creation code so it will work after reuse...
>
> >> -Rich
>
> >> On May 4, 2009, at 12:27 AM, Chris Schepman <csc...@gmail.com> wrote:
>
> >> I just realized that ...
>
> >> statusLabel.text = [[person statuses] objectAtIndex:indexPath.row];
>
> >> [statusLabel sizeToFit];
>
> >> seems to work without having to make the calculation again. I suppose it's
> >> making it for us...still tinkering with the  cell reuse though.
>
> >> On Sun, May 3, 2009 at 10:14 PM, Rich MacDonald <<rich.macdon...@gmail.com>
> >> rich.macdon...@gmail.com> wrote:
>
> >>> I haven't figured out - or read in these threads - any solutions that
> >>> don't involve making this height calculation twice or at least caching the
> >>> height in an array for quicker look-up the second time.  This does seem a
> >>> bit inefficient/inelegant, and I too would love to hear if there is a better
> >>> solution.
>
> >>> In regards to the tableView:cellForRowAtIndexPath:, we're creating the
> >>> UITableViewCell ourselves so I hadn't put much stake in getting a useful
> >>> height from that (i.e. what we calculated from
> >>> tableView:heightForRowAtIndexPath: ).  The dequeueReusableCellWithIdentifier:
> >>> UITableView method sounded like it might set the height for us, but it
> >>> seems like it's just returning a cell with the values when it was added to
> >>> the queue...definitely getting different heights than just 44 after
> >>> scrolling back through the table.
>
> >>> One possibility is to use
>
> >>> - (void)tableView:(UITableView *)tableView
> >>> willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath
> >>> *)indexPath
>
> >>> which is a delegate method called after tableView:cellForRowAtIndexPath:
> >>>   The cell passed here does indeed have the correct height for its frame, so
> >>> you could alter the label height backwards from that.  But after doing this
> >>> successfully, I'm not sure I like the solution for two reasons:
>
> >>>    1. It requires a similar amount of code to work backwards from the
> >>>    row height.  This seems no better than duplicating row height calculation
> >>>    code; and it is worse in that duplicating the code verbatim is only one
> >>>    thing to figure out instead of two.
> >>>    2. It sounds like this delegate isn't intended for this kind of
> >>>    alteration (from Table View Programming Guide):
>
> >>> The table view’s data source implementation of
> >>> tableView:cellForRowAtIndexPath: should *always* reset all content when
> >>> reusing a cell. In addition, a table view sends a
> >>> tableView:willDisplayCell:forRowAtIndexPath: message to its delegate
> >>> just before it draws a row. If the delegate chooses to implement this
> >>> method, it can customize the cell object before it is displayed. Note that
> >>> the delegate in this method should change state-based properties set earlier
> >>> by the table view, such as selection and background color, and not content.
>
> >>> So in the end, calculating the height once and caching it for later use
> >>> may be the most efficient route.  Just have to make sure to invalidate the
> >>> cache if needed (e.g. rotation change causing cell width resizing).
>
> >>> -Rich
>
> >>> On Sun, May 3, 2009 at 4:42 PM, Chris Schepman < <csc...@gmail.com>
> >>> csc...@gmail.com> wrote:
>
> >>>> I'm struggling with this right now as well. It's like you have to
> >>>> calculate the display height for the cell. Then you have to calculate the
> >>>> same thing inside cellForRowAtIndexPath and set the contentView to the right
> >>>> size as well. I don't think the contentView is being sized with the cell...
>
> >>>> I'm not sure the cell is being sized either actually...it keeps coming
> >>>> in at a height of 44, even thought the heightForRowAtIndexPath is making the
> >>>> cells visibly much larger.
>
> >>>> hmm...I'm going to keep tinkering and I'll post if I find something that
> >>>> works. :)
>
>  Woz Comp.png
> 23KViewDownload

Jeff

unread,
May 5, 2009, 12:16:41 AM5/5/09
to iPhone Application Development Auditors
Uhh... when computing the height of the cell and how you are going to
truncate words that don't fit on the same line, you are using two
different LineBreakModes... Sounds kinda... wrong (but I haven't
tested it myself). I'm just assuming that
UILineBreakModeTailTruncation and UILineBreakModeWordWrap don't do the
same thing.

WBSKI

unread,
May 5, 2009, 12:55:39 AM5/5/09
to iPhone Application Development Auditors
Good idea, I forgot to change that back. However I changed the code
back to UILineBreakModeWordWrap and it still is messed up. Maybe
someone could post a code snippet?

Cheers
> ...
>
> read more »

Rich MacDonald

unread,
May 5, 2009, 1:15:24 AM5/5/09
to iphone-appd...@googlegroups.com
WBSKI, I looked through your earlier code and was also looking for any inconsistencies in width, font, line-break, etc.  You're doing all the other steps I have with my status label:  UILineBreakModeWordWrap, numberOfLines = 0; setting same font size as in tableView:heightForRowAtIndexPath.  

Could you post your updated code with cell reuse?  It's possible you moved some code to the one-time creation that still needs to be called each time a cell is presented.  

-Rich

Paul_Madrid

unread,
May 5, 2009, 9:03:07 AM5/5/09
to iPhone Application Development Auditors

This works fro me:

UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;

UILabel *statusLabel = [[[UILabel alloc] initWithFrame:CGRectMake(5,
5, 295, 30)] autorelease];
statusLabel.font = [UIFont systemFontOfSize:12.0];
statusLabel.textColor = [UIColor blackColor];
statusLabel.lineBreakMode = UILineBreakModeWordWrap;
statusLabel.numberOfLines = 0;
statusLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight;
statusLabel.text = [self.aPerson.statusMessages objectAtIndex:
[indexPath row]];

[cell.contentView addSubview:statusLabel];
}

return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
(NSIndexPath *)indexPath {
NSString *text = [self.aPerson.statusMessages objectAtIndex:
[indexPath row]];
UIFont *font = [UIFont systemFontOfSize:12.0];
CGSize withinSize = CGSizeMake(tableView.bounds.size.width ,
1000.0);
CGSize size = [text sizeWithFont:font constrainedToSize:withinSize
lineBreakMode:UILineBreakModeWordWrap];
return size.height + 20.0; // Points
> ...
>
> read more »

WBSKI

unread,
May 5, 2009, 10:32:41 AM5/5/09
to iPhone Application Development Auditors
Not quite sure how that works since you are only setting text when the
cell is not being reused..

Here is Alan C's proposed implementation (using UILabel tag, so when
the cell is reused, it detects that the UILabel is already allocated,
and doesn't allocate a new one, just sets the text and bounds):

const int kStatusLabelTag = 0x11111111;

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"VariableHeightCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier] autorelease];
}

UILabel *statusLabel = [cell viewWithTag:kStatusLabelTag];
if (!statusLabel)
{
statusLabel = [[[UILabel alloc]
initWithFrame:cell.contentView.bounds] autorelease];
[statusLabel setNumberOfLines:0];
[statusLabel setLineBreakMode:UILineBreakModeWordWrap];
[statusLabel setFont:[UIFont systemFontOfSize:16]];
[cell.contentView addSubview:statusLabel];
}

[statusLabel setText:[[person statusMessages]
objectAtIndex:indexPath.row]];
CGFloat statusLabelWidth = tableView.bounds.size.width - 40;
[statusLabel setFrame:CGRectMake(10, 10, statusLabelWidth, 20)];
[statusLabel sizeToFit];

return cell;
> ...
>
> read more »

WBSKI

unread,
May 5, 2009, 10:48:13 AM5/5/09
to iPhone Application Development Auditors
That code has a couple things you have to fix in it.

Here is the final, fully working code:

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"VariableHeightCell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier] autorelease];
}

UILabel *statusLabel = (UILabel *)[cell.contentView viewWithTag:
10];
if (!statusLabel)
{
statusLabel = [[[UILabel alloc]
initWithFrame:cell.contentView.bounds] autorelease];
[statusLabel setTag:10];
[statusLabel setNumberOfLines:0];
[statusLabel setLineBreakMode:UILineBreakModeWordWrap];
[statusLabel setFont:[UIFont systemFontOfSize:16]];
[cell.contentView addSubview:statusLabel];
}

[statusLabel setText:[[person statusMessages]
objectAtIndex:indexPath.row]];
CGFloat statusLabelWidth = tableView.bounds.size.width - 40;
[statusLabel setFrame:CGRectMake(10, 10, statusLabelWidth, 20)];
[statusLabel sizeToFit];

return cell;
}

> ...
>
> read more »

grouchal

unread,
May 5, 2009, 10:54:01 AM5/5/09
to iPhone Application Development Auditors
AutoResizeMask - was all I needed to solve this!

Thanks for the tips

Mark Struik

unread,
May 10, 2009, 9:54:46 AM5/10/09
to iPhone Application Development Auditors
static NSString *CellIdentifier = @"MyCell";

UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}

UILabel *statusLabel = nil;


for ( id currentChild in cell.contentView.subviews )
{
if ( [currentChild isKindOfClass:[UILabel class]] )
{
statusLabel = currentChild;
}
}

if ( statusLabel == nil )
{
statusLabel = [[[UILabel alloc] initWithFrame:CGRectMake(5, 5, 295,
30)] autorelease];
statusLabel.font = [UIFont systemFontOfSize:12.0];
statusLabel.textColor = [UIColor blackColor];
statusLabel.lineBreakMode = UILineBreakModeWordWrap;
statusLabel.numberOfLines = 0;
statusLabel.autoresizingMask = UIViewAutoresizingFlexibleHeight;
statusLabel.text = [displayPerson.statusUpdates
objectAtIndex:indexPath.row];

[cell.contentView addSubview:statusLabel];
}
else
{
statusLabel.text = [displayPerson.statusUpdates
objectAtIndex:indexPath.row];
}

return cell;

is actualy better.. this is re-using the already created label :)

On 5 mei, 16:54, grouchal <grouc...@gmail.com> wrote:
> AutoResizeMask - was all I needed to solve this!
>
> Thanks for the tips
>
> On May 5, 3:03 pm, Paul_Madrid <pauljbroder...@gmail.com> wrote:
>
>
>
> > This works fro me:
>
> >    UITableViewCell*cell = [tableView
> > dequeueReusableCellWithIdentifier:CellIdentifier];
> >     if (cell == nil) {
> >         cell = [[[UITableViewCellalloc] initWithFrame:CGRectZero
> > > > > > > >>>UITableViewCellourselves so I hadn't put much stake in getting a
> > > > useful
> > > > > > > >>> height from that (i.e. what we calculated from
> > > > > > > >>> tableView:heightForRowAtIndexPath: ).  The
> > > > dequeueReusableCellWithIdentifier:
> > > > > > > >>> UITableView method sounded like it might set the height for us,
> > > > but it
> > > > > > > >>> seems like it's just returning a cell with the values when it was
> > > > added to
> > > > > > > >>> the queue...definitely getting different heights than just 44
> > > > after
> > > > > > > >>> scrolling back through the table.
>
> > > > > > > >>> One possibility is to use
>
> > > > > > > >>> - (void)tableView:(UITableView *)tableView
> > > > > > > >>> willDisplayCell:(UITableViewCell*)cell
> > > > forRowAtIndexPath:(NSIndexPath
> > > > > > > >>> *)indexPath
>
> > > > > > > >>> which is a delegate method called after
> > > > tableView:cellForRowAtIndexPath:
> > > > > > > >>>   The cell passed here does indeed have the correct height for
> > > > its
>
> ...
>
> meer lezen »

osca...@gmail.com

unread,
May 10, 2009, 11:09:14 AM5/10/09
to iPhone Application Development Auditors
Hi Mark,

Here in
statusLabel = [[[UILabel alloc] initWithFrame:CGRectMake(5, 5, 295,
30)] autorelease];

How do u get the numbers 295, 30?

Thanks!
> ...
>
> read more »

Stevnie

unread,
May 16, 2009, 5:47:27 PM5/16/09
to iPhone Application Development Auditors
Thanks everyone!

Here's the correct implementation:

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"DefaultCell"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero
reuseIdentifier:@"DefaultCell"] autorelease];
}
[cell.textLabel setText: [timeLine objectAtIndex:indexPath.row]];
//[cell.textLabel setLineBreakMode:UILineBreakModeWordWrap];
[cell.textLabel setNumberOfLines:0];
[cell.textLabel setFont:[UIFont boldSystemFontOfSize :18]];
//[cell.textLabel sizeToFit];
return cell;
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
(NSIndexPath *)indexPath
{
NSString *text = [timeLine objectAtIndex:indexPath.row];
UIFont *font = [UIFont boldSystemFontOfSize :18];
CGSize withinSize = CGSizeMake(tableView.bounds.size.width, 1000.0);
CGSize size = [text sizeWithFont:font constrainedToSize:withinSize
lineBreakMode:UILineBreakModeWordWrap];
return size.height+30.0;
}

Thanks again!

Steve
> > > > > inconsistencies in width, font,line-break, etc.  You're doing all the other
> > > > > steps I have with my status label:  UILineBreakModeWordWrap, numberOfLines =
> > > > > 0; setting same font size as in tableView:heightForRowAtIndexPath.
> > > > > Could you post your updated code with cell reuse?  It's possible you moved
> > > > > some code to the one-time creation that still needs to be called each time a
> > > > > cell is presented.
>
> > > > > -Rich
>
> > > > > On Mon, May 4, 2009 at 9:55 PM, WBSKI <skiinf...@gmail.com> wrote:
>
> > > > > > Good idea, I forgot to change that back. However I changed the code
> > > > > > back to UILineBreakModeWordWrap and it still is messed up. Maybe
> > > > > > someone could post a code snippet?
>
> > > > > > Cheers
>
> > > > > > On May 4, 9:16 pm, Jeff <dagame...@gmail.com> wrote:
> > > > > > > Uhh... when computing the height of the cell and how you are going to
> > > > > > > truncate words that don't fit on the sameline, you are using two
> ...
>
> read more »

Phil

unread,
May 16, 2009, 7:05:55 PM5/16/09
to iPhone Application Development Auditors
Curious... you have implemented tableView:heightForRowAtIndexPath:
but you never seem to call it.

-Phil
> ...
>
> read more »

Stevnie

unread,
May 16, 2009, 7:57:59 PM5/16/09
to iPhone Application Development Auditors
I think it's all done by the tableview when it loads the cell(If you
set up break point here, you will know what's going on inside). We
don't need to call it directly!
> ...
>
> read more »

Daan van Dijk

unread,
May 17, 2009, 2:53:41 AM5/17/09
to iphone-appd...@googlegroups.com
Exactly. However, you may call it if for some reason you want to know
the size of a specific cell. It's not like dealloc, which you should
not call ever (except [super alloc]).

Gil

unread,
May 17, 2009, 5:51:38 AM5/17/09
to iPhone Application Development Auditors
Hey I am having a problem with your solution. I can't click on the
rows anymore. What could be the reason for this behavior?
> ...
>
> Erfahren Sie mehr »
Reply all
Reply to author
Forward
0 new messages