UILabel in a grouped table view's header doesn't wrap text - iphone

I have a label whose text is longer that the table view's header containing it, so I want the label to be split into N lines according to the width available. This is my code:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 1) {
UIView *wrapper = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
[wrapper setBackgroundColor:[UIColor clearColor]];
UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 100)];
textLabel.text = NSLocalizedString(#"This is supposed to be a very long text that may fill several lines", #"");
[textLabel setLineBreakMode:UILineBreakModeWordWrap];
[textLabel setNumberOfLines:0];
[wrapper addSubview:textLabel];
return wrapper;
}
else
return nil;
}
However, the label is in a single line and I can't see the end of the text. What am I missing?
Thanks!

You should implement the delegate method heightForHeaderInSection.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if(section ==1)
return 100;
else
return 0;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 1) {
NSString *text = NSLocalizedString(#"This is supposed to be a very long text that may fill several lines", #"");;
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:10] constrainedToSize:CGSizeMake(self.tableView.frame.size.width, 999) lineBreakMode:NSLineBreakByWordWrapping];
CGRect frame = CGRectZero;
frame.size = size;
UIView *wrapper = [[UIView alloc] initWithFrame:frame];
[wrapper setBackgroundColor:[UIColor clearColor]];
UILabel *textLabel = [[UILabel alloc] initWithFrame:frame];
textLabel.text = NSLocalizedString(#"This is supposed to be a very long text that may fill several lines", #"");
[textLabel setLineBreakMode:UILineBreakModeWordWrap];
[textLabel setNumberOfLines:0];
[wrapper addSubview:textLabel];
return wrapper;
}
else
return nil;
}

use this if you want to support iOS below 6.0
textLabel.lineBreakMode = UILineBreakModeWordWrap;
textLabel.numberOfLines = 0;
As UILineBreakModeWordWrap deprecated now.
otherwise use this
textLabel.lineBreakMode = NSLineBreakByWordWrapping;
textLabel.numberOfLines = 0;

you should set size of label as text in heightForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *text;
CGSize textViewSize;
int width = 270;
textViewSize = [text sizeWithFont:[UIFont fontWithName:#"Helvetica Neue" size:14.0]
constrainedToSize:CGSizeMake(width, FLT_MAX)
lineBreakMode:UILineBreakModeCharacterWrap];
CGFloat height = MAX(textViewSize.height, 44.0f);
return height;
}
and in cellForRowAtIndexPath write this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
textViewSize = [text sizeWithFont:[UIFont fontWithName:#"Helvetica Neue" size:14.0]
constrainedToSize:CGSizeMake(width, FLT_MAX)
lineBreakMode:UILineBreakModeCharacterWrap];
// / CGFloat height = MAX(textViewSize.height, 44.0f);
// if (!lblParameter){
// lblParameter = (UILabel*)[cell viewWithTag:1];}
CGFloat height = MAX(textViewSize.height, 44.0f);
[lblParameter setText:text];
[lblParameter setFont:[UIFont fontWithName:#"Helvetica Neue" size:14.0]];
[lblParameter setFrame:CGRectMake(10, 0,width,height)];
[[cell contentView] addSubview:lblParameter];
}

you need caculate the height of uilabel this height equal font size * numberline

It seems that wrapping / formatting will not work on a label inside the header view - presumably because it's inheriting defaults from somewhere. So, a simple solution, which AFAIK breaks no laws, is to put the label inside a view inside the header view.
Using the storyboard, drag a view to the table view controller (above your prototype cell).
Add a second view to this view.
Add the label to this second view. Make sure both views and label are tall enough to allow for multiple lines of text. In the label's attributes, set Lines to 0 and Line Breaks to Word Wrap.
Wrapping will now work as expected.

Related

Dynamic UITableViewCell per UILable height with landscape portrait orientation support

I need to create a cell height according to lable's content with orientation support curretly have tried this and working fine for portrait but not in landscape so need solution which works on both so if any one can please help me.
thanks in advance for your efforts.
this is my code in tableview
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *arr = [arrData objectAtIndex:tableView.tag];
NSString *text = [arr objectAtIndex:indexPath.row];
CGSize constraint = CGSizeMake(contentWidth - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:20] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
CGFloat height = MAX(size.height, 44.0f);
return height + (CELL_CONTENT_MARGIN * 2);
}
// Customize the appearance of table view cells.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
UILabel *label = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
cell.accessoryView = nil;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setLineBreakMode:NSLineBreakByWordWrapping];
[label setNumberOfLines:0];
[label setFont:[UIFont systemFontOfSize:20]];
[label setTag:1];
[label setBackgroundColor:[UIColor redColor]];
[[cell contentView] addSubview:label];
}
NSArray *arr = [arrData objectAtIndex:tableView.tag];
NSString *text = [arr objectAtIndex:indexPath.row];
CGSize constraint = CGSizeMake(contentWidth - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:20] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
if (!label)
label = (UILabel*)[cell viewWithTag:1];
[label setText:text];
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, contentWidth - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
return cell;
}
In heightForRowAtIndexPath you can set height according to orientation.
when orientation change, reload cells. In heightForRowAtIndexPath use this value to check orientation and while this method is called -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration reload your cells.
So your heightForRowAtIndexPath will be somethign like this
if(UIInterfaceOrientationIsPortrait(orientation)){
}
else
{
}
Make sure you keep your cells subviews as autoresizing flexible.

Activate View for header delegate for specific section in single table

I am developing an application in which I need header to customize and add my own button just for single section. I googled and done some code where I am able to add button, but I am facing two issue.
Titles of other's section is not showing.
Button not show properly because of tableview scroll size same after adding button.
Here is what I am doing.
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIView * headerView = [[[UIView alloc] initWithFrame:CGRectMake(1, 0, tableView.bounds.size.width, 40)] autorelease];
[headerView setBackgroundColor:[UIColor clearColor]];
if(section==2){
float width = tableView.bounds.size.width;
int fontSize = 18;
int padding = 10;
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(padding, 2, width - padding, fontSize)];
label.text = #"Texto";
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor whiteColor];
label.shadowColor = [UIColor darkGrayColor];
label.shadowOffset = CGSizeMake(0,1);
label.font = [UIFont boldSystemFontOfSize:fontSize];
[headerView addSubview:label];
UIButton * registerButton = [UIButton buttonWithType:UIButtonTypeCustom];
[registerButton setImage:[UIImage imageNamed:#"P_register_btn.png"] forState:UIControlStateNormal];
[registerButton setFrame:CGRectMake(0, 0, 320, 150)];
[headerView addSubview:registerButton];
return headerView;
}
return headerView;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 3;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if(section==0)
return #"Registration";
else if(section==1)
return #"Player Detail";
return nil;
}
Here is Image of my out put in which Texto text show but button is under that area where the end limit of table view scroll height and also section 0 and 1 title is not showing I also block code for first and second section in viewforheaderinsection. Thanks in advance.
The other header names don't appear because the viewForHeader method only answers for section 2. Once implemented, the datasource expects that method to be the authority on all headers. Just add some else logic for the other sections....
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UIView * headerView;
UILabel *label;
if (section==2) {
headerView = [[[UIView alloc] initWithFrame:CGRectMake(1, 0, tableView.bounds.size.width, 40)] autorelease];
[headerView setBackgroundColor:[UIColor clearColor]];
// and so on
return headerView;
} else if (section == 0) {
label = [[[UILabel alloc] initWithFrame:CGRectMake(0,0,tableView.bounds.size.width, 44)] autorelease];
label.text = #"Section 0 Title";
return label;
} else .. and so on
The header answered by this method looks to be 40px high (see initWithFrame), but the button being added is 150px high (see setFrame: for the button). That's the likely the root cause of the button issue. Try implementing:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return (section == 2)? 150.0 : UITableViewAutomaticDimension;
}

iOS - UILabel inside tableview cell

I'm very much new to iphone development and strucked at a point. Actually my need is I'm displaying some results in a UITableView and I'm displaying then UILables of UITableView's cell..
How can I make the UILabel's to adjust the content according to the text. Actually text is not static .It may be changing at run time.So I need to set dynamic size to a UILabel .Ans secondly suppose if the text is null then it should not show any space and immediately the next UILabel should start .How can I make it possible ?
Here is my code..
self.tableView=[[UITableView alloc] initWithFrame:CGRectMake(0,150,320,800) style:UITableViewStylePlain];
self.tableView.delegate=self;
self.tableView.dataSource=self;
self.tableView.scrollEnabled = NO;
[self.view addSubview:self.tableView];
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(currentHtmlElement==#"3")
{
static NSString *CellIdentifier=#"Cell";
UITableViewCell* cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
}
NSMutableDictionary *d = (NSMutableDictionary *) [arr2 objectAtIndex:indexPath.row];
cell.accessoryType= UITableViewCellAccessoryDetailDisclosureButton;
UILabel *name1= [[UILabel alloc]initWithFrame:CGRectMake(10, 5, 320, 40)];
name1.font=[UIFont boldSystemFontOfSize:16];
[name1 setTextAlignment:UITextAlignmentLeft];
[name1 setText:[d valueForKey:#"Name"]];
name1.tag = 111;
[cell addSubview:name1];
[name1 release];
UILabel *codetype=[[UILabel alloc]initWithFrame:CGRectMake(10, 45, 320,15)];
codetype .font=[UIFont boldSystemFontOfSize:12];
[codetype setTextAlignment:UITextAlignmentLeft];
[codetype setText:[d valueForKey:#"Code"]];
codetype.tag=112;
[cell addSubview:codetype];
[codetype release];
UILabel *id=[[UILabel alloc]initWithFrame:CGRectMake(10, 68, 320,10)];
id .font=[UIFont fontWithName:#"arial" size:12];
[id setTextAlignment:UITextAlignmentLeft];
[id setText:[d valueForKey:#"ID"]];
id.tag=113;
[cell id ];
[id release];
UILabel *address=[[UILabel alloc]initWithFrame:CGRectMake(10, 85, 320,10)];
address .font=[UIFont fontWithName:#"arial" size:12];
[address setTextAlignment:UITextAlignmentLeft];
[address setText:[d valueForKey:#"address"]];
line2.tag=114;
[cell addSubview: address];
[address release];
UILabel *city = [[UILabel alloc]initWithFrame:CGRectMake(10, 105, 320, 10)];
city .font=[UIFont fontWithName:#"arial" size:12];
[city setTextAlignment:UITextAlignmentLeft];
[city setText:[d valueForKey:#"City"]];
city.tag=115;
[cell addSubview:city ];
[city release];
}
Here I have set all the UILabels to static size.But what I need is dynamic size.and suppose if the address label is null then it should not show any space and next label i.e city should start immediately next after id ..How is it possible?
I did this task in my code.... you can use this code and do changes according to your code....and let me know if you get any problem.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
NSMutableDictionary *dicNotification =[[NSMutableDictionary alloc]initWithDictionary: [myNotification objectAtIndex:indexPath.row]];
//code to get notification text height
NSString *text = [dicNotification objectForKey:#"message"];
CGSize constraint = CGSizeMake(175, 100.0f);
CGSize size = [text sizeWithFont: [UIFont fontWithName:#"Verdana" size:12] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
return size.height;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
//label for message
UILabel *lblMsg = [[UILabel alloc] initWithFrame:CGRectZero];
lblMsg.tag = 12;
lblMsg.backgroundColor = [UIColor clearColor];
[lblMsg setFont:[UIFont fontWithName:#"Verdana" size:12]];
[lblMsg setLineBreakMode:UILineBreakModeWordWrap];
[cell addSubview:lblMsg];
}
NSMutableDictionary *dicNotification =[[NSMutableDictionary alloc]initWithDictionary: [myNotification objectAtIndex:indexPath.row]];
//get the message height set frame height to imageView(BubbleMid & Top) & labelMSG
NSString *txt = [dicNotification objectForKey:#"message"];
CGSize constraint = CGSizeMake(175, 2000.0f);
CGSize size = [txt sizeWithFont: [UIFont fontWithName:#"Verdana" size:12] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
//set frame height to labelMsg
UILabel *lblMsg = (UILabel *)[cell viewWithTag:12];
lblMsg.frame = CGRectMake(15,25, 175, size.height);
[lblMsg setNumberOfLines:size.height/16];
//set labelMsg text
lblMsg.text = [dicNotification objectForKey:#"message"];
return cell;
}
The thing is that you must use heightForRowAtIndexPath. The problem is that it is called prior to cellForRowAtIndexPath, therefore the text is not in the component and you can not simply adjust the component size to the text. So, what you do is calculate the text size using a sizeWithFont.
In case of normal/standard text
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//here you get your text string
NSString* theText = ... ;
//then calculate the size. systemFontOfSize depends on your font size
//yourLabelWidth must be known and usually depends on scree size or if the tableview has an index
CGSize textSize = [theText sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(yourLabelWidth, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
return textSize.height;
}
In the case of attributed text
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//here you get your text string
NSAttributedString* theText = ...;
//then calculate the size.
//yourLabelWidth must be known and usually depends on scree size or if the tableview has an index
CGRect rectSize = [theText boundingRectWithSize:CGSizeMake(yourLabelWidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin context:NULL];
return rectSize.size.height;
return textSize.height;
}
you can make UILable adjust content with bellow code
CGSize sizeToMakeLabel = [name1.text sizeWithFont: name1.font];
name1.frame = CGRectMake(name1.frame.origin.x, name1.frame.origin.y,
sizeToMakeLabel.width, sizeToMakeLabel.height);
and here set second lable like bellow..
UPDATE
if([[d valueForKey:#"address"] isEquelToString:#""]){
UILabel *city=[[UILabel alloc]initWithFrame:CGRectMake(10, idLable.frame.origin.y + id.frame.size.height+10 , 320,15)];
city .font=[UIFont fontWithName:#"arial" size:12];
[city setTextAlignment:UITextAlignmentLeft];
[city setText:[d valueForKey:#"City"]];
city.tag=115;
[cell addSubview:city ];
CGSize sizeToMakeLabel = [city.text sizeWithFont: city.font];
city.frame = CGRectMake(city.frame.origin.x, city.frame.origin.y,
sizeToMakeLabel.width, sizeToMakeLabel.height);
}
else{
UILabel * address =[[UILabel alloc]initWithFrame:CGRectMake(10, idLable.frame.origin.y + id.frame.size.height+10 , 320,15)];
address .font=[UIFont fontWithName:#"arial" size:12];
[address setTextAlignment:UITextAlignmentLeft];
[address setText:[d valueForKey:#"address"]];
line2.tag=114;
[cell addSubview: address];
CGSize sizeToMakeLabel = [address.text sizeWithFont: address.font];
address.frame = CGRectMake(address.frame.origin.x, address.frame.origin.y,
sizeToMakeLabel.width, sizeToMakeLabel.height);
}
and so on for every label..
follow this logic for whole label
i hope this help you...

dynamic calculation of UILabel width in UITableViewCell

I am building a custom, in-application settings view based on UITableViewCellStyle1 (or so).
I am trying to dynamically calculate the width of the left label (title) of a cell to determine how wide my text field on the right can be.
When I launch the app in the simulator and the view loads, the width of the title labels is zero until I scroll down the view and a cell is not visible, then when I scroll back up the size adjusts as expected. I believe this might have to do something with cell reusage.
I need the title labels in the cells to have their correct width when the view loads, not after they have gone out of sight one time.
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString* reuseIdentifier = #"SettingsCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if ( !cell )
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier] autorelease];
[cell setBackgroundColor:[UIColor baeDarkGrayColor]];
UILabel* cellLabel = [cell textLabel];
[cellLabel setTextColor:[UIColor whiteColor]];
[cellLabel setBackgroundColor:[UIColor clearColor]];
[cell setUserInteractionEnabled:YES];
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
}
// Populate cell with corresponding data.
NSDictionary* tableSection = [_tableData objectAtIndex:indexPath.section];
// Set the label
UILabel* textLabel = [cell textLabel];
NSString* labelString = [[tableSection objectForKey:#"itemTitles"] objectAtIndex:indexPath.row];
[textLabel setText:labelString];
// CGSize constrainedSize;
// constrainedSize.width = MAXFLOAT;
// constrainedSize.height = MAXFLOAT;
CGSize textLabelSize = [textLabel.text sizeWithFont:textLabel.font /*constrainedToSize:constrainedSize*/];
NSLog(#"text label width: %f", textLabelSize.width);
// Set the accessory view
BAESettingsTableCellAccessoryType accessoryType = [[[tableSection objectForKey:#"itemAccessories"] objectAtIndex:indexPath.row] integerValue];
switch ( accessoryType )
{
case BAESettingsTableCellAccessoryDisclosureIndicator:
{
UIImageView* disclosureView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"AccessoryDisclosure.png"]];
[cell setAccessoryView:disclosureView];
[disclosureView release];
break;
}
case BAESettingsTableCellAccessoryOnOffSwitch:
{
UISwitch* onOffSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
[onOffSwitch setOn:YES];
[cell setAccessoryView:onOffSwitch];
[onOffSwitch release];
break;
}
case BAESettingsTableCellAccessoryNone:
// default:
// break;
{
CGRect cellFrame = [cell frame];
float detailTextFieldWidth = cellFrame.size.width - ( textLabelSize.width + 50 );
float detailTextFieldHeight = cellFrame.size.height - 1;
NSLog(#"detail text field calculated frame width, height, %f, %f", detailTextFieldWidth, detailTextFieldHeight);
CGRect frame = CGRectMake(cellFrame.origin.x, cellFrame.origin.y, detailTextFieldWidth, detailTextFieldHeight);
UITextField* textField = [[UITextField alloc] initWithFrame:frame];
NSString* detailLabelString = [[tableSection objectForKey:#"itemDetailStrings"] objectAtIndex:indexPath.row];
textField.text = detailLabelString;
textField.textColor = cell.detailTextLabel.textColor;
textField.textAlignment = UITextAlignmentRight;
textField.borderStyle = UITextBorderStyleRoundedRect;
[cell setAccessoryView:textField];
[textField release];
break;
}
}
return cell;
}
Explicitly setting the font solves your problem.
CGSize textLabelSize = [textLabel.text sizeWithFont:[UIFont systemFontOfSize:17]];
Gory Detals:
When the tableview first loads, this snippet returns zero width due to the font size being 0.
[textLabel.text sizeWithFont:textLabel.font]
I figured this out by displaying the point size of the cell font.
NSLog(#"font size: %f", cell.textLabel.font.pointSize);
The point size was zero until the cell went off screen and came back, just as you described.
I completely agree that it's sufficiently annoying that it should be a bug. Why would the nice folks at Apple ever ask for the cell height without ensuring the cell is completely set up. Silly! However, instead of using a deprecated function, try:
[cell layoutIfNeeded];
Calling this method has the same effect with the cell being set up including the bounds, cell font, etc. Therefore, any calculation after this has access to the fully set up cell. Here's the whole code:
-(CGFloat) tableView:(UITableView *) tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath {
// Find the cell for this index path
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
CGFloat cellHeight = cell.frame.size.height;
// Calculate text size after forcing a layout
[cell layoutIfNeeded];
CGSize textSize = [cell.textLabel.text sizeWithFont:cell.textLabel.font constrainedToSize:CGSizeMake(cell.contentView.bounds.size.width, 99999) lineBreakMode:cell.textLabel.lineBreakMode];
// Only change the cell height if the text forces a growth
if (textSize.height > cellHeight) {
cellHeight = textSize.height;
}
return cellHeight;
}
I found the same issue, but I've found a workaround. FYI I've raised an bug with Apple (Bug ID# 7535066). Lex, in your example, if you use cell.font instead of textLabel.font, it should work, although you will get a compiler warning, as this is a deprecated method call. I'm not sure if you'll be able to see the details of the bug I raised, so I'm pasting the details here:
iPhone SDK 3.1.2 (7D11) NSString UIKit Additions method sizeWithFont returns nil
SUMMARY
I am decorating UITableViewCells in the UITableView delegate method:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
I wish to find length of the text already in the cell, to correctly format the new view, so I am calling the NSString UIKit Additions method:
(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
When I use cell.textLabel.font for the font argument, it always returns an empty CGSize
IF I use the DEPRECATED method, cell.font for the argument, it DOES return the CGSize value as expected.
STEPS TO REPRODUCE
1. Create a UITableViewController with a TableView, and populate it with some sample data
2. In the stubbed method cellForRowAtIndexPath, after the comment //Set up the cell, and where the cell.textLabel.text is populated, put the following:
CGSize size = [cell.textLabel.text sizeWithFont:[[cell textLabel] font] constrainedToSize:CGSizeMake(320, 480)];
NSLog(#"cell frame: %f %f", size.width, size.height);
CGSize size2 = [cell.textLabel.text sizeWithFont:[cell font] constrainedToSize:CGSizeMake(320, 480)];
NSLog(#"DEPRECATED cell frame: %f %f", size2.width, size2.height);
EXPECTED RESULTS
If anything, you would expect the call that uses the Deprecated method to retrieve the font, to fail, or at least both to return the same result.
ACTUAL RESULT:
2010-01-12 22:06:36.645 PrefTest[9659:207] cell frame: 0.000000 0.000000
2010-01-12 22:06:36.646 PrefTest[9659:207] DEPRECATED cell frame: 88.000000 24.000000
WORKAROUND & ISOLATION:
As noted, use the deprecated method to get the font. But it gets stranger!
Reverse the two methods I gave above:
CGSize size2 = [cell.textLabel.text sizeWithFont:[cell font] constrainedToSize:CGSizeMake(320, 480)];
NSLog(#"DEPRECATED cell frame: %f %f", size2.width, size2.height);
CGSize size = [cell.textLabel.text sizeWithFont:[[cell textLabel] font] constrainedToSize:CGSizeMake(320, 480)];
NSLog(#"cell frame: %f %f", size.width, size.height);
The results are now:
2010-01-12 22:06:36.645 PrefTest[9659:207] cell frame: 88.000000 24.000000
2010-01-12 22:06:36.646 PrefTest[9659:207] DEPRECATED cell frame: 88.000000 24.000000
It seems that just referencing [cell font] is enough to force [[cell textLabel] font] to work correctly.
Use [myLbl sizeToFit]; to automatically resize the label.
Here is the sample code.
UILabel *lbl1, *lbl2;
if (cell == nil) {
UILabel *lbl1 = [[UILabel alloc] init];
[lbl1 setFont:[UIFont boldSystemFontOfSize:20]];
[cell.contentView addSubview:lbl1];
lbl1.frame = CGRectMake(3, 10, 0, 0);
lbl1.tag = 10;
[lbl1 release];
UILabel *lbl2 = [[UILabel alloc] init];
[lbl2 setFont:[UIFont systemFontOfSize:20]];
[cell.contentView addSubview:lbl2];
lbl2.tag = 20;
[lbl2 release];
}
else {
lbl1 = (UILabel*)[cell.contentView viewWithTag:10];
lbl2 = (UILabel*)[cell.contentView viewWithTag:20];
}
lbl1.text = #"Hello ";
[lbl1 sizeToFit];
lbl2.text = #"World";
[lbl2 sizeToFit];
lbl2.frame = CGRectMake(lbl1.frame.origin.x+lbl1.frame.size.width+5,
lbl1.frame.origin.y,
lbl2.frame.size.width,
lbl1.frame.size.height);

Cant set the height of my uitableviewcell right

I set the size of my UITableCellĀ“s with this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString * vergleich = [nachricht objectAtIndex:indexPath.row];
CGSize size = [vergleich sizeWithFont:[UIFont fontWithName:#"Helvetica" size:14]
constrainedToSize:CGSizeMake(268, MAX_HEIGHT)
lineBreakMode:UILineBreakModeWordWrap];
return size.height + 30;
}
nachricht is a NSArray which contains all the messages. The code just looks how long the message (with a specified font) is and calculate the height. I set + 30, because over the message(UITextView) is a UIlabel.
The UITextView, which should contain the messages, get the size with this code:
- (void)setTweetText:(NSString *)_tweet;{
CGSize size = [_tweet sizeWithFont:[UIFont fontWithName:#"Helvetica" size:14]
constrainedToSize:CGSizeMake(268, MAX_HEIGHT)
lineBreakMode:UILineBreakModeWordWrap];
[textText setFrame:CGRectMake(55, 25, 268, size.height + 10)];
textText.text = _tweet;
[textText sizeToFit];
textText.dataDetectorTypes = UIDataDetectorTypeLink;
}
Now there is a problem and I don't know why: The UITextView is bigger then the cell, even if I set the size of the cell height there is a unpleasant distance between the TextView and the next cell. Why doesn't he get the right height for some cells. Here is an example:
alt text http://img34.imageshack.us/img34/214/bildschirmfoto20100120uw.png
All I can say is in my cellForRowAtIndexPath I use the following and it works. My heightForRowAtIndexPath is nearly identical to yours.
double d = [self tableView:table heightForRowAtIndexPath:indexPath];
UILabel* label = [[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 280, d-20)] autorelease];
label.numberOfLines = 100;
label.lineBreakMode = UILineBreakModeWordWrap;
[label setFont:[UIFont boldSystemFontOfSize:[UIFont smallSystemFontSize]]];
label.text = [descriptions objectAtIndex:indexPath.section];
[cell.contentView addSubview:label];
one possibility is you have set the CGSize width to be different in each function, for row height you have CGSizeMake(268, MAX_HEIGHT) and for setTweetText it is CGSizeMake(262, MAX_HEIGHT)
its not a good idea to sizeWithFont from that method, its fairly heavy and will chop up your scrolling performance. if possible calculate the heights before and store them for quick access from that method