First, label.font
might be not a string:
The font to use, currently may be either a CTFontRef, a CGFontRef, or a string naming the font
So you'd better perform some checks if you're not setting it in your code (I'll write my example in ObjC, but it should be pretty simple to translate it to Swift):
NSString* fontName;
CFTypeRef font = label.font;
if (CFGetTypeID(font) == CFStringGetTypeID())
{
fontName = (__bridge NSString *)(font);
}
else if (CFGetTypeID(font) == CGFontGetTypeID())
{
fontName = CFBridgingRelease(CGFontCopyFullName((CGFontRef)font));
}
else if (CFGetTypeID(font) == CTFontGetTypeID())
{
fontName = CFBridgingRelease(CTFontCopyFullName((CTFontRef)font));
}
Second, CATextLayer (unlike UILabel or string drawing functions) seems to use line height multiple different from 1 when drawing string content, so you need to use paragraph style to measure it correctly:
NSMutableParagraphStyle* style = [[NSMutableParagraphStyle alloc] init];
style.lineHeightMultiple = 1.05;
NSDictionary* attributes = @{
NSFontAttributeName: [UIFont fontWithName:fontName size:label.fontSize],
NSParagraphStyleAttributeName: style
};
CGSize textSize = [str sizeWithAttributes:attributes];
Multiplier 1.05 was actually chosen after some experiments, and it works pretty good for different font sizes from 8 to 72.