In iOS7, sizeWithFont is deprecated, so I am using boundingRectWithSize(which returns a CGRect value). My code:
UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
// you can use your font.
CGSize maximumLabelSize = CGSizeMake(310, 9999);
CGRect textRect = [myString boundingRectWithSize:maximumLabelSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:fontText}
context:nil];
expectedLabelSize = CGSizeMake(textRect.size.width, textRect.size.height);
In textRect, I'm getting a size greater than my maximumLabelSize, a different size than when using sizeWithFont. How can I resolve this issue?
How about create new label and using sizeThatFit:(CGSize)size ??
UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:#"YOUR FONT's NAME" size:16];
gettingSizeLabel.text = #"YOUR LABEL's TEXT";
gettingSizeLabel.numberOfLines = 0;
gettingSizeLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
CGSize expectSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];
Edit: This upper code is not good for ios 7 and above, so please use below:
CGRect textRect = [myString boundingRectWithSize:maximumLabelSize
options:NSStringDrawingUsesLineFragmentOrigin| NSStringDrawingUsesFontLeading
attributes:#{NSFontAttributeName:fontText}
context:nil];
Maybe you need to provide additional option to the method that is suggested in this answer:
CGSize maximumLabelSize = CGSizeMake(310, CGFLOAT_MAX);
CGRect textRect = [myString boundingRectWithSize:maximumLabelSize
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName: fontText}
context:nil];
Here is my working code snippet:
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:attributeDict];
NSString *headline = [dict objectForKey:#"title"];
UIFont *font = [UIFont boldSystemFontOfSize:18];
CGRect rect = [headline boundingRectWithSize:CGSizeMake(300, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:#{NSFontAttributeName:font} context:nil];
CGFloat height = roundf(rect.size.height +4)
I added 4px to the calculated height, because without these 4px, there is one line missing.
I use this code snippet in a tableView and add the "height" to an array of NSNumbers and I get the correct cell height for the default textLabel.
Add 4 more pixel if you want more space under the text in the textLabel.
**** UPDATE ****
I do not agree with the "width bug of 40px", I shout be the 4px of missing height, because 4px is the default height of a space between a letter and the bound of a single line.
You can check it with a UILabel, for a fontsize of 16 you need a UILabel height of 20.
But if your last line has no "g" or whatever in it, the measuring could be miss the 4px of height.
I rechecked it with a little method, I get an accurate height of 20,40 or 60
for my label and a right width less than 300px.
To support iOS6 and iOS7, you can use my method:
- (CGFloat)heightFromString:(NSString*)text withFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
CGRect rect;
float iosVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (iosVersion >= 7.0) {
rect = [text boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:#{NSFontAttributeName:font} context:nil];
}
else {
CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
rect = CGRectMake(0, 0, size.width, size.height);
}
NSLog(#"%#: W: %.f, H: %.f", self, rect.size.width, rect.size.height);
return rect.size.height;
}
**** UPGRADE ****
Thanks to your comments, I upgraded my function as followed. Since sizeWithFont is deprecated and you will get a warning in XCode, I added the diagnostic-pragma-code to remove the warning for this particular function-call/block of code.
- (CGFloat)heightFromStringWithFont:(UIFont*)font constraintToWidth:(CGFloat)width
{
CGRect rect;
if ([self respondsToSelector:#selector(boundingRectWithSize:options:attributes:context:)]) {
rect = [self boundingRectWithSize:CGSizeMake(width, 1000) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:#{NSFontAttributeName:font} context:nil];
}
else {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
CGSize size = [self sizeWithFont:font constrainedToSize:CGSizeMake(width, 1000) lineBreakMode:NSLineBreakByWordWrapping];
rect = CGRectMake(0, 0, size.width, size.height);
#pragma GCC diagnostic pop
}
return ceil(rect.size.height);
}
In addition to the 4px topic:
depending which font and font-weight you use, the calculation returns different height-values. In my case: HelveticaNeue-Medium with a fontsize of 16.0 returns a line-height of 20.0 for a single line but 39.0 for two lines, 78px for 4 lines --> 1px missing for every line - beginning with line 2 - but you want to have your fontsize + 4px linespace for every line you have to get a height-result.
Please keep that in mind while coding!
I don´t have a function yet for this "problem" but I will update this post when I´m finished.
If I understand correctly, you are using boundingRectWithSize: just as a way of getting the size you would get with sizeWithFont (meaning you want directly the CGSize, not the CGRect)?
This looks like what you are looking for :
Replacement for deprecated sizeWithFont: in iOS 7?
They are using sizeWithAttributes: to get the size, as a replacement for sizeWithFont.
Do you still get the wrong size using something like this :
UIFont *fontText = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16];
// you can use your font.
expectedLabelSize = [myString sizeWithAttributes:#{NSFontAttributeName:fontText}];
The #SoftDesigner's comment has worked for me
CGRect descriptionRect = [description boundingRectWithSize:CGSizeMake(width, 0)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
attributes:#{NSFontAttributeName : [UIFont systemFontOfSize:12]}
context:nil];
result = ceil(descriptionRect.size.height);
for finding size of label run time sizewithfont is deprecated for iOS 7.0 instead of that you have to use -boundingRectWithSize:options:attributes:context: method
you can use it like below code
CGSize constraint = CGSizeMake(MAXIMUM_WIDHT, TEMP_HEIGHT);
NSRange range = NSMakeRange(0, [[self.message body] length]);
NSDictionary *attributes = [YOUR_LABEL.attributedText attributesAtIndex:0 effectiveRange:&range];
CGSize boundingBox = [myString boundingRectWithSize:constraint options:NSStringDrawingUsesFontLeading attributes:attributes context:nil].size;
int numberOfLine = ceil((boundingBox.width) / YOUR_LABEL.frame.size.width);
CGSize descSize = CGSizeMake(ceil(boundingBox.width), ceil(self.lblMessageDetail.frame.size.height*numberOfLine));
CGRect frame=YOUR_LABEL.frame;
frame.size.height=descSize.height;
YOUR_LABEL.frame=frame;
here you have to give width to maximum length for finding height or width.
try this it is working for me.
Related
I am using the following method to determine the height required to display the text that i have. However i cannot get the correct height without truncating the text at the end.
CGRect labelRect = [comment boundingRectWithSize:headerMax
options:NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading
attributes:#{NSFontAttributeName:font}
context:nil];
How can i say not to determine the required label height without truncating the text at the end. I want the whole text to fit into the label.
-(CGRect)getLabelSizeWithText:(NSString *)textLabel forFontSize:(CGFloat) fontSize
{
CGRect textRect;
if (textLabel != nil)
{
NSAttributedString *actualString = [[NSAttributedString alloc] initWithString:textLabel attributes:#{NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue" size:fontSize]} ];
NSStringDrawingContext *targetContext = [[NSStringDrawingContext alloc] init];
CGFloat commentLabelWidth = [[UIScreen mainScreen]bounds].size.width;
textRect = [actualString boundingRectWithSize:CGSizeMake(commentLabelWidth, 900) options:NSStringDrawingUsesLineFragmentOrigin context:targetContext];
}
return textRect;
}
This one should work. Try it
Use -
1. If you want word wrap -
labelView.lineBreakMode = NSLineBreakByWordWrapping;
labelView.numberOfLines = 2;
CGRect labelRect = [comment boundingRectWithSize:headerMax
options:NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading | NSLineBreakByWordWrapping
attributes:#{NSFontAttributeName:font}
context:nil];
2. If you Don't want truncating tail at all -
// No line break mode
labelView.numberOfLines = 0;
CGRect labelRect = [comment boundingRectWithSize:headerMax
options:NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading
attributes:#{NSFontAttributeName:font}
context:nil];
Try this
NSString *cellText = restaurant.review;
UIFont *cellFont = [UIFont systemFontOfSize:14.0];
NSDictionary *attributes = #{NSFontAttributeName: cellFont};
CGRect labelSize = [cellText boundingRectWithSize:CGSizeMake([UIScreen mainScreen].bounds.size.width-20, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil];
I am not really sure whether I understood your question correctly; it sounds like you are trying to calculate the frame size needed to display the text and setting the frame manually with that. Additionally, by setting .numberOfLines = 2, you are limiting the text that you can show. My suggestion would be for you to set up constraints via autolayout, optionally add a .minimumScaleFactor and let it dynamically resize itself.
If you still want to calculate size, with numberOfLines taken into consideration, you can use a prototype label and have use its height
- (CGSize)preferredSizeForString:(NSString *)string
width:(CGFloat)width
{
UILabel *prototypelabel = [UILabel new];
prototypelabel.frame = CGRectMake(0, 0, width, 0);
prototypelabel.text = #"Your string";
prototypelabel.numberOfLines = 2;
[prototypelabel sizeToFit];
return prototypelabel.frame.size;
}
I'm getting the width of a UILabel [after the text has been set] with:
myUILabel.frame.width
but its always the same width, no matter if it holds the String: "Hello." or the String: "Hello everyone on this planet.". But the UILabel needs to have a bigger width with the second String.
Try myUILabel.intrinsicContentSize(). Make sure you set your font first, of course.
You should use [label sizeToFit]
sizeToFit on label will stretch the label to accommodate the text.
The other solution is to calculate the width of the string and reframe the label based on the strings width.
For the second solution you can calculate the size of string as
CGSize strSize = CGSizeZero;
CGSize minSize = CGSizeZero;
if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
{
NSAttributedString *attributedText = [[[NSAttributedString alloc] initWithString:text attributes:#{NSFontAttributeName: label.font}] autorelease];
CGRect rect = [attributedText boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
strSize = rect.size;
}
else
{
strSize = [text sizeWithFont:label.font constrainedToSize:constraintSize];
}
Try
myUILabel.intrinsicContentSize.width
Or
myUILabel.intrinsicContentSize().width
This question already has answers here:
How to calculate UILabel height dynamically?
(14 answers)
Closed 5 years ago.
I have the following code:
label.numberOfLines = 0; // allows label to have as many lines as needed
label.text = #"some long text";
[label sizeToFit];
How do I get the height of label in points?
The easiest way to get the height is sizeThatFits. Use it like this:
Objective-C
CGFloat maxLabelWidth = 100;
CGSize neededSize = [label sizeThatFits:CGSizeMake(maxLabelWidth, CGFLOAT_MAX)];
Swift 3.0
let maxLabelWidth: CGFloat = 100
let neededSize = label.sizeThatFits(CGSize(width: maxLabelWidth, height: CGFloat.greatestFiniteMagnitude))
The height your label needs is neededSize.height.
Note that im using CGFLOAT_MAX for the size height, to make sure the label has enough place to fit in the CGSize.
The height of your label also depends on your width of the label, thats why I added maxLabelWidth, it makes a difference if the label can be 100pt wide or 200pt.
Hope this helps!
Edit:
Make sure you set label.numberOfLines = 0; otherwise neededSize returns the size where the text is in a single line.
Edit:
Added Swift version, although the naming is a bit weird, greatestFiniteMagnitude seems to be the correct equivalent for CGFLOAT_MAX.
Use following method to calculate dynamic UILabel height:
- (CGFloat)getLabelHeight:(UILabel*)label
{
CGSize constraint = CGSizeMake(label.frame.size.width, CGFLOAT_MAX);
CGSize size;
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGSize boundingBox = [label.text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:label.font}
context:context].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
return size.height;
}
Just use [label sizeThatFits:label.frame.size]; and it will return the size of label which will fit for given text. Or you can also follow the question
For those who want to estimate the size a label takes in a method which estimates header / cell height in UICollectionView or UITableView, follow this:
Set maxWidth that your label will take
Create a new UILabel and set numberOfLines to 0
Add Font attributes like custom font name and font size if using custom fonts
Set text for this label and get estimated height using sizeThatFits. Label height is neededHeight.height
Swift Version
let maxLabelWidth:CGFloat = collectionView.frame.width - 20
let label = UILabel()
label.numberOfLines = 0
let addressFont = [ NSFontAttributeName: UIFont(name: "OpenSans", size: 12.0)! ]
let addr = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
label.attributedText = NSMutableAttributedString(string: addr , attributes: addressFont )
let neededSize:CGSize = label.sizeThatFits(CGSizeMake(maxLabelWidth, CGFloat.max))
let labelHeight = neededSize.height
Thanks to #FabioBerger
I edited Salman Zaidi's answer a little to make it work better for myself. It works well if you don't have direct access to a label, like when you are trying to get label height in heightForRowAtIndexPath:
-(CGFloat)getLabelHeight:(CGSize)labelSize string: (NSString *)string font: (UIFont *)font{
CGSize size;
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGSize boundingBox = [string boundingRectWithSize:labelSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:context].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
return size.height;
}
You can Create Label dynamically :
-(CGRect)newLableSize:(NSString *)lableString
{
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
CGFloat tempwidth = YourStaticLabelWidth * ScreenWidth / 320;
NSMutableArray *array=[[NSMutableArray alloc]initWithObjects: lableString,nil];
CGRect newLabelsize = [[array objectAtIndex:0] boundingRectWithSize:CGSizeMake(tempwidth, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName:selectFont,NSParagraphStyleAttributeName:paragraphStyle} context:nil];
NSLog(#"New Label Size Width : %f",newLabelsize.size.width);
NSLog(#"New Label Size Height : %f",newLabelsize.size.height);
return newLabelsize;
}
I'm adjust height, with 2 lines in my label
lblUserQuestion.preferredMaxLayoutWidth = 100.0f;
100.0f, it's a size i wanted, and another line,
[lblUserQuestion sizeToFit];
My method complete is,
UILabel *lblUserQuestion = [[UILabel alloc] initWithFrame:CGRectMake(61, 25, self.frame.size.width-61-20, 37.0f)];
lblUserQuestion.numberOfLines= 0;
lblUserQuestion.font =[UIFont fontWithName:#"HelveticaNeue-Thin" size:14.];
lblUserQuestion.adjustsFontSizeToFitWidth = YES;
lblUserQuestion.minimumScaleFactor = 0.5;
lblUserQuestion.preferredMaxLayoutWidth= 100.0f;
lblUserQuestion.text = _photoToVote.label;
- (CGFloat)getTextHeightByWidth:(NSString*)text textFont:(UIFont*)textFont textWidth:(float)textWidth {
if (!text) {
return 0;
}
CGSize boundingSize = CGSizeMake(textWidth, CGFLOAT_MAX);
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:#{ NSFontAttributeName: textFont }];
CGRect rect = [attributedText boundingRectWithSize:boundingSize options:NSStringDrawingUsesLineFragmentOrigin context:nil];
CGSize requiredSize = rect.size;
return requiredSize.height;
}
- (CGFloat)getTextWidthByHeight:(NSString*)text textFont:(UIFont*)textFont textHeight:(float)textHeight {
if (!text) {
return 0.0f;
}
CGSize boundingSize = CGSizeMake(CGFLOAT_MAX, textHeight);
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text
attributes:#{ NSFontAttributeName: textFont }];
CGRect rect = [attributedText boundingRectWithSize:boundingSize
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize requiredSize = rect.size;
return requiredSize.width;
}
Use this function
+ (CGFloat)heightForText:(NSString*)text font:(UIFont*)font withinWidth:(CGFloat)width {
CGSize constraint = CGSizeMake(width, 20000.0f);
CGSize size;
CGSize boundingBox = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:font}
context:nil].size;
size = CGSizeMake(ceil(boundingBox.width), ceil(boundingBox.height));
return size.height;
}
- (CGFloat)getLabelsize:(UILabel *)label
{
CGSize maxSize = CGSizeMake(label.frame.size.width, 9999);
CGSize requiredSize = [label sizeThatFits:maxSize];
return requiredSize.height;
}
Converting a project from iOS5.0 to iOS7 / iOS6 on Xcode 5. The code below is giving a compile time warning:
'sizeWithFont:constrainedToSize:lineBreakMode:'is deprecated: first deprecated in ios 7.0 - Use - boundingRectWithSize:options:attribiutes:context
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0)
{
self.lblHidden.frame = CGRectMake(58, 228, 945, 9999);
self.lblHidden.text = detailShareObj.pDesc;
CGSize size = [detailShareObj.pDesc sizeWithFont:self.lblHidden.font constrainedToSize:self.lblHidden.frame.size lineBreakMode:NSLineBreakByWordWrapping];
return 228.0+size.height+20;
}
else if (indexPath.section == 1)
{
NSString *tempPointStr = (self.shortDescArray)[indexPath.row];
self.lblHidden.frame = CGRectMake(58, 0, 945, 9999);
self.lblHidden.text = tempPointStr;
CGSize size = [tempPointStr sizeWithFont:self.lblHidden.font
constrainedToSize:self.lblHidden.frame.size
lineBreakMode:NSLineBreakByWordWrapping];
return 50.0f;
}
I tried some of the suggestion give elsewhere but nothing is up to rescue if some one can help by giving the corrections required in the code will be greatly appreciated.
I wouldn't just mask the deprecated function warning. They deprecated it for a reason. I believe the function was deprecated because that series of NSString+UIKit functions were based on the UIStringDrawing library, which wasn't thread safe. If you tried to run them not on the main thread (like any other UIKit functionality), you'll get unpredictable behaviors. In particular, if you ran the function on multiple threads simultaneously, it'll probably crash your app. This is why in iOS 6, they introduced a the boundingRectWithSize:... method for NSAttributedStrings. This was built on top of the NSStringDrawing libraries and is thread safe.
If you look at the new NSString boundingRectWithSize:... function, it asks for an attributes array in the same manner as a NSAttributeString. If I had to guess, this new NSString function in iOS 7 is merely a wrapper for the NSAttributeString function from iOS 6.
On that note, if you were only supporting iOS 6 and iOS 7, then I would definitely change all of your NSString's sizeWithFont:... to the NSAttributeString's boundingRectWithSize. It'll save you a lot of headache if you happen to have a weird multi-threading corner case! Here's how I converted NSString's sizeWithFont:constrainedToSize::
What used to be:
NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
CGSize size = [text sizeWithFont:font
constrainedToSize:(CGSize){width, CGFLOAT_MAX}];
Can be replaced with:
NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
NSAttributedString *attributedText =
[[NSAttributedString alloc]
initWithString:text
attributes:#
{
NSFontAttributeName: font
}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
Please note the documentation mentions:
In iOS 7 and later, this method returns fractional sizes (in the size
component of the returned CGRect); to use a returned size to size
views, you must use raise its value to the nearest higher integer
using the ceil function.
So to pull out the calculated height or width to be used for sizing views, I would use:
CGFloat height = ceilf(size.height);
CGFloat width = ceilf(size.width);
If you want it compatible with both iOS7 and the versions below it, try this one (with ARC):
CGSize size;
if ([tempPointStr respondsToSelector:
#selector(boundingRectWithSize:options:attributes:context:)])
{
NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
paragraphStyle.alignment = NSTextAlignmentLeft;
NSDictionary * attributes = #{NSFontAttributeName : self.lblHidden.font,
NSParagraphStyleAttributeName : paragraphStyle};
size = [tempPointStr boundingRectWithSize:self.lblHidden.frame.size
options:NSStringDrawingUsesFontLeading
|NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil].size;
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
size = [tempPointStr sizeWithFont:self.lblHidden.font
constrainedToSize:self.lblHidden.frame.size
lineBreakMode:NSLineBreakByWordWrapping];
#pragma clang diagnostic pop
}
Note: It's just an example for your else-if case, maybe you need to do some modification depend on what you want it be. ;)
For iOS7, replace:
CGSize size = [tempPointStr sizeWithFont:self.lblHidden.font
constrainedToSize:self.lblHidden.frame.size
lineBreakMode:NSLineBreakByWordWrapping];
With:
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; //set the line break mode
NSDictionary *attrDict = [NSDictionary dictionaryWithObjectsAndKeys:self.lblHidden.font, NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil];
CGSize size = [tempPointStr boundingRectWithSize:self.lblHidden.frame.size
options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin
attributes:attrDict context:nil].size;
You can use:
UIFont *font = [UIFont boldSystemFontOfSize:16];
CGRect new = [string boundingRectWithSize:CGSizeMake(200, 300)
options:NSStringDrawingUsesFontLeading
attributes:#{NSFontAttributeName: font}
context:nil];
CGSize stringSize= new.size;
If you're targeting iOS 6.0+, you can still use sizeWithFont:constrainedToSize:lineBreakMode:. Just make sure that your project's iOS Deployment Target is set for 6.0, and the compiler won't give you these warnings.
(You can find this by clicking on the blue project tab (usually at the top of the left, project navigator pane) within the "info" section).
If you're only targeting iOS 7.0+, you should use the new method boundingRectWithSize:options:attributes:context.
You can find the Apple docs on this new method here.
The boundingRectWithSize:options:attributes:context has the problem, that it does not calculates the height correctly if the String contains "\n" (line breaks). Therefore this code calculates the size for each line separately for a given width (inWidth):
NSArray *brokenByLines=[string componentsSeparatedByString:#"\n"];
CGFloat height=0.0;
CGFloat maxWidth=0.0;
for (NSString* actString in brokenByLines) {
CGRect tSize=[actString boundingRectWithSize:CGSizeMake(inWidth, 600) options:(NSStringDrawingUsesLineFragmentOrigin | NSLineBreakByWordWrapping) attributes:#{NSFontAttributeName: inFont} context:nil];
if (maxWidth<tSize.size.width) {
maxWidth=tSize.size.width;
}
height+=tSize.size.height;
}
CGSize size= CGSizeMake(ceil(maxWidth), ceil(height));
In iOS 7, the method:
- (CGSize)sizeWithFont:(UIFont *)font
constrainedToSize:(CGSize)size
lineBreakMode:(NSLineBreakMode)lineBreakMode
and the method:
- (CGSize)sizeWithFont:(UIFont *)font
are deprecated. How can I replace
CGSize size = [string sizeWithFont:font
constrainedToSize:constrainSize
lineBreakMode:NSLineBreakByWordWrapping];
and:
CGSize size = [string sizeWithFont:font];
You could try this:
CGRect textRect = [text boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:FONT}
context:nil];
CGSize size = textRect.size;
Just change "FONT" for an "[UIFont font....]"
As we cant use sizeWithAttributes for all iOS greater than 4.3 we have to write conditional code for 7.0 and previous iOS.
1) Solution 1:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
CGSize size = CGSizeMake(230,9999);
CGRect textRect = [specialityObj.name
boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont fontWithName:[AppHandlers zHandler].fontName size:14]}
context:nil];
total_height = total_height + textRect.size.height;
}
else {
CGSize maximumLabelSize = CGSizeMake(230,9999);
expectedLabelSize = [specialityObj.name sizeWithFont:[UIFont fontWithName:[AppHandlers zHandler].fontName size:14] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap]; //iOS 6 and previous.
total_height = total_height + expectedLabelSize.height;
}
2) Solution 2
UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont fontWithName:[AppHandlers zHandler].fontName size:16]; // Your Font-style whatever you want to use.
gettingSizeLabel.text = #"YOUR TEXT HERE";
gettingSizeLabel.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(310, 9999); // this width will be as per your requirement
CGSize expectedSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];
The first solution is sometime fail to return proper value of height. so use another solution. which will work perfectly.
The second option is quite well and working smoothly in all iOS without conditional code.
Here is simple solution :
Requirements :
CGSize maximumSize = CGSizeMake(widthHere, MAXFLOAT);
UIFont *font = [UIFont systemFontOfSize:sizeHere];
Now As constrainedToSizeusage:lineBreakMode: usage is deprecated in iOS 7.0:
CGSize expectedSize = [stringHere sizeWithFont:font constrainedToSize:maximumSize lineBreakMode:NSLineBreakByWordWrapping];
Now usage in greater version of iOS 7.0 will be:
// Let's make an NSAttributedString first
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:stringHere];
//Add LineBreakMode
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
[paragraphStyle setLineBreakMode:NSLineBreakByWordWrapping];
[attributedString setAttributes:#{NSParagraphStyleAttributeName:paragraphStyle} range:NSMakeRange(0, attributedString.length)];
// Add Font
[attributedString setAttributes:#{NSFontAttributeName:font} range:NSMakeRange(0, attributedString.length)];
//Now let's make the Bounding Rect
CGSize expectedSize = [attributedString boundingRectWithSize:maximumSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
Below are two simple methods that will replace these two deprecated methods.
And here are the relevant references:
If you are using NSLineBreakByWordWrapping, you don't need to specify the NSParagraphStyle, as that is the default:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSParagraphStyle_Class/index.html#//apple_ref/occ/clm/NSParagraphStyle/defaultParagraphStyle
You must get the ceil of the size, to match the deprecated methods' results.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSString_UIKit_Additions/#//apple_ref/occ/instm/NSString/boundingRectWithSize:options:attributes:context:
+ (CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font {
CGSize size = [text sizeWithAttributes:#{NSFontAttributeName: font}];
return CGSizeMake(ceilf(size.width), ceilf(size.height));
}
+ (CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{
CGRect textRect = [text boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName: font}
context:nil];
return CGSizeMake(ceilf(textRect.size.width), ceilf(textRect.size.height));
}
In most cases I used the method sizeWithFont:constrainedToSize:lineBreakMode: to estimate the minimum size for a UILabel to accomodate its text (especially when the label has to be placed inside a UITableViewCell)...
...If this is exactly your situation you can simpy use the method:
CGSize size = [myLabel textRectForBounds:myLabel.frame limitedToNumberOfLines:mylabel.numberOfLines].size;
Hope this might help.
UIFont *font = [UIFont boldSystemFontOfSize:16];
CGRect new = [string boundingRectWithSize:CGSizeMake(200, 300) options:NSStringDrawingUsesFontLeading attributes:#{NSFontAttributeName: font} context:nil];
CGSize stringSize= new.size;
[Accepted answer works nicely in a category. I'm overwriting the deprecated method names. Is this a good idea? Seems to work with no complaints in Xcode 6.x]
This works if your Deployment Target is 7.0 or greater. Category is NSString (Util)
NSString+Util.h
- (CGSize)sizeWithFont:(UIFont *) font;
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size;
NSString+Util.m
- (CGSize)sizeWithFont:(UIFont *) font {
NSDictionary *fontAsAttributes = #{NSFontAttributeName:font};
return [self sizeWithAttributes:fontAsAttributes];
}
- (CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size {
NSDictionary *fontAsAttributes = #{NSFontAttributeName:font};
CGRect retVal = [self boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:fontAsAttributes context:nil];
return retVal.size;
}
UIFont *font = [UIFont fontWithName:#"Courier" size:16.0f];
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
paragraphStyle.alignment = NSTextAlignmentRight;
NSDictionary *attributes = #{ NSFontAttributeName: font,
NSParagraphStyleAttributeName: paragraphStyle };
CGRect textRect = [text boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:attributes
context:nil];
CGSize size = textRect.size;
from two answers 1 + 2