Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS7's deprecation of NSString's drawAtPoint:forWidth:withFont:minFontSize:actualFontSize:lineBreakMode:baselineAdjustment:

With iOS7's release, the following function has been deprecated:

drawAtPoint:forWidth:withFont:minFontSize:actualFontSize:lineBreakMode:baselineAdjustment:

In Apple's documentation it suggests to use

drawInRect:withAttributes:

The reason I use this function is because of the <code>minFontSize</code> parameter, which lets me draw a string inside a rect.

If the text won't fit, it will first shrink the text size to <code>minFontSize</code> and then if it doesn't fit, it will truncate it.

I am unable to accomplish this so far using <code>drawInRect:withAttributes:</code>.

Which key I can use to determine the <code>minFontSize</code> equivalent?

like image 510
Rob Avatar asked Sep 20 '13 18:09

Rob


2 Answers

It is a little more complicated than before and you cannot use a minimum font size, but have to use minimum font scale factor. There is also a bug in the iOS SDK, which breaks it for most use cases (see notes at the bottom). Here is what you have to do:

// Create text attributes
NSDictionary *textAttributes = @{NSFontAttributeName: [UIFont systemFontOfSize:18.0]};

// Create string drawing context
NSStringDrawingContext *drawingContext = [[NSStringDrawingContext alloc] init];
drawingContext.minimumScaleFactor = 0.5; // Half the font size

CGRect drawRect = CGRectMake(0.0, 0.0, 200.0, 100.0);
[string drawWithRect:drawRect
             options:NSStringDrawingUsesLineFragmentOrigin
          attributes:textAttributes
             context:drawingContext];

Notes:

  • There seems to be a bug in the iOS 7 SDK at least up to version 7.0.3: If you specify a custom font in the attributes, the miniumScaleFactor is ignored. If you pass nil for the attributes, the text is scaled correctly.

  • The NSStringDrawingUsesLineFragmentOrigin option is important. It tells the text drawing system, that the drawing rect's origin should be at the top left corner.

  • There is no way to set the baselineAdjustment using the new method. You would have to do that yourself by calling boundingRectWithSize:options:attributes:context: first and then adjusting the rect before you pass it to drawWithRect:options:attributes:context.

like image 128
Florian Avatar answered Sep 24 '22 09:09

Florian


After googling for a long time I did not find a solution working under iOS7.

Right now I use the following workaround, knowing that it is very ugly.

I render a UILabel in memory, take a screenshot and draw that.

UILabel is able to shrink the text correctly.

Perhaps someone finds it useful.

UILabel *myLabel = [[UILabel alloc] initWithFrame:myLabelFrame];
myLabel.font = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:16];
myLabel.text = @"Some text that is too long";
myLabel.minimumScaleFactor = 0.5;
myLabel.adjustsFontSizeToFitWidth = YES;
myLabel.backgroundColor = [UIColor clearColor];

UIGraphicsBeginImageContextWithOptions(myLabelFrame.size, NO, 0.0f);
[[myLabel layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

[screenshot drawInRect:myLabel.frame];
like image 31
Shingoo Avatar answered Sep 25 '22 09:09

Shingoo