Reputation: 9754
I got an old project, and the code is using sizeWithFont. I got an warning from xcode saying it is first deprecated in iOS 7, and asked me to replace it with
(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context
I got two questions:
I. if I intend not to change it, what whould happen? Will it crash my app, or just bypass the deprecated API?
II. I wanted to use the suggested API, but I am confused it is asking for a CGSize paramter and returning a CGRect, while my old project just needs to return a CGSize. If I already got the CGSize, why I need the rect again? Please correct me and give code using the new API. Thanks a lot!
EDIT:
I have checked the answer in Replacement for deprecated sizeWithFont: in iOS 7?
I will do a self-answer to compare two solutions.
Another quesiton I have is:
I notice there is a [self setNumberOfLines:1];
, should I keep it or I can delete it? It does not impact anything in my code for now, but I don't know other situations, aka 'multiple line' situlation.
Old legacy code:
@implementation UILabel (dynamicSize)
-(CGFloat)expectedWidth{
[self setNumberOfLines:1];
CGSize maximumLabelSize = CGSizeMake(9999,self.frame.size.height);
CGSize expectedLabelSize = [[self text] sizeWithFont:[self font]
constrainedToSize:maximumLabelSize
lineBreakMode:[self lineBreakMode]];
return expectedLabelSize.width;
}
@end
Upvotes: 0
Views: 918
Reputation: 26383
There are miss concepts about the two methods, if you are tring to get the size of a text container such as UITexView
or UILabel
, this methods only give you the space occupied by the text, and not by the view, with multiple rows this can lead to clipped text, for instante UITextView
contains some padding, those methods doesn't take into account that.
Instead calling -sizeToFit
on the text view after adding the text gives you the real size.
About your questions:
.size
inside the CGRect
struct.UILabel
will cut the text with rule selected in the -linebreakMode
, use 0 to have no restrictionUpvotes: 0
Reputation: 3389
You can provide the CGFLOAT_MAX in width if your label need to change width as per text size while put CGFLOAT_MAX in height if you want hight as per text in label. The other param will be static.
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:[self text]
//If Height is dynamic and width is fix, Eg.150 width fix, and height dynamic
CGRect rect = [attributedText boundingRectWithSize:(CGSize){150, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
// OR
//If width is dynamic and Height is fix, Eg.150 Height fix, and width dynamic
CGRect rect = [attributedText boundingRectWithSize:(CGSize){CGFLOAT_MAX,150}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
You will get dynamic width, height as per your label size required.
Upvotes: 0
Reputation: 9754
I will do a self-answer to compare two solutions from Replacement for deprecated sizeWithFont: in iOS 7?
BTW I am not sure if I need to setNumberOfLines, so I will set it to no limit
[self setNumberOfLines:0];
One solution is
CGSize size = [[self text] sizeWithAttributes:@{NSFontAttributeName: [self font]}];
// Values are fractional -- you should take the ceilf to get equivalent values
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
Another one:
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:[self text]
attributes:@{NSFontAttributeName: [self font]}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){CGFLOAT_MAX, CGFLOAT_MAX} // be careful here
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
CGSize adjustedSize = CGSizeMake(ceilf(size.width), ceilf(size.height));
Both solution gives the same result as the deprecated API. To summerize, I use sizeWithAttributes because it is simpler.
However one thing to mention that:
the answer in Replacement for deprecated sizeWithFont: in iOS 7? uses kinds of (CGSize){width, CGFLOAT_MAX}];
as the size parameter,
but I tested if I use it like (CGSize){self.bounds.size.width, CGFLOAT_MAX}];
The result is not correct, the calculated width is less than the other solution.
If I use (CGSize){CGFLOAT_MAX, CGFLOAT_MAX}
, I will get the same result as the other answer. Test your code before you decide choosing a solution.
Upvotes: 0