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

10,917

Solution 1

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.

Solution 2

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];
Share:
10,917

Related videos on Youtube

Rob
Author by

Rob

Updated on September 26, 2022

Comments

  • Rob
    Rob over 1 year

    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?

  • Rob
    Rob over 10 years
    adding minFontSize as a key doesn't really change anything.
  • heczaco
    heczaco over 10 years
    yep, sorry, i didn't read your question correctly, I couldn't find any key in the documentation that does exactly what minFontSize would do, but maybe playing with this key would work, "NSStrokeWidthAttributeName" , hope it helps
  • Rob
    Rob over 10 years
    According to the documentation, your answer is correct. However, as you indicate, there seems to be a bug and this is getting ignored. I didn't try your suggestion of leaving attributes nil, since I do require to pass in some attributes, or the returned size will be incorrect anyway. I'm marking this answer as correct. Thank you!
  • Aaron
    Aaron almost 7 years
    Add some additional context to this answer to help people understand why this is a good answer, rather than just posting raw code.