UIAppFonts – custom fonts with the iPhone/iPad 3.2 SDK

Recently I had some problems getting custom fonts working with the new iPhone/iPad 3.2 SDK using Interface Builder. In the new SDK it’s supposed to be really easy in theory, but there is currently a bug with Interface Builder/xCode that ruins it. I’ll share my workaround how to get it to work and if you have better ideas – I would be really grateful to hear abut them.

First, the way it’s supposed to work:

  • Add the custom font to your Xcode project
  • Add the name of the *.ttf (I’ve also had success with *.ttc) file to your Info.plist under UIAppFonts (Array)
  • Set the font property of any UILabel to match your newly added font name (you can discover the actual font names by iterating over [UIFont familyNames] and [UIFont fontNamesForFamily])

When done manually in code it should look something like this:

// MyViewController.h
@interface MyViewController : UIViewController {
 UILabel *myLabel;
}

// connect with IB
@property(nonatomic, retain) IBOutlet UILabel *myLabel;

@end

// MyViewController.m
@implementation MyViewController

@synthesize myLabel;

- (void) viewDidLoad {
 [myLabel setFont: [UIFont fontWithName: @"Quake" size: myLabel.font.pointSize]];
}

@end

While the above does work, connecting every UILabel manually to an IBOutlet and then implementing the same thing over and over again for each label seemed like a bad idea. My workaround was to define a custom UILabel subclass for each different custom font I needed to use (fortunately only 4) and then use those subclasses instead in Interface Builder:

// LabelQuake.h
#import <uikit /UIKit.h>
@interface LabelQuake : UILabel {

}

@end

// LabelQuake.m
#import "LabelQuake.h"
@implementation LabelQuake

- (id)initWithCoder:(NSCoder *)decoder {
 
 if (self = [super initWithCoder: decoder]) {
 [self setFont: [UIFont fontWithName: @"Quake" size: self.font.pointSize]];
 }
 
 return self;
}


@end

This way my controllers don’t have to know about every label and it’s SEMI-DRY ;)

!PS: people not using IB, but building their UI in code should just ignore the above, everything should just work.
!PS: I’ll update this post when the bug gets updated/closed in Radar with more info.

Tarmo Lehtpuu
Tarmo is the swiss army knife Software Engineer. His deep knowledge on wide range of technologies makes him an efficient problem solver. In addition to Ruby on Rails, he enjoys developing iOS Apps.

21 Comments

  • alvin

    Should setFont be sent to the label instead of self in the UIViewController example?

    • Tarmo Lehtpuu

      Thanks alvin, fixed the typo.

  • Anthony

    This is nice. Really nice.

  • Jamison Dance

    Do you have a link to the bug report? I would like to follow the issue on Radar.

  • Tarmo Lehtpuu

    As far as I understand radar bug reports are only visible to Apple and the reporter. But the bug report ID is 7976255 and it’s marked as duplicate of 7672035. Hope that helps :)

  • YS

    Hi, thanks for the post. Will this work for adding foreign language support such a custom arabic font?

    • Mustafa

      Just FYI, this method doesn’t work for custom arabic fonts (and arabic text). I tried to display the font using UILabel, UITextField, UITextView and FontLabel (by Zynga).

  • Jim

    Hi,
    I’m very new so this may seem like a dumb question. Where you have written ‘connect with IB’… how do I do that? I would suspect it’s a fairly simple matter of dragging a noodle but I am going to need some guidance to get this right.

    Thank you,
    Jim

  • Jehiah

    can you cross-post your apple bug report to http://openradar.appspot.com/ ?

  • Vitaliy

    Thank you! It’s GREAT!

  • Kamleshwar

    Really nice and informative article.

    Thanks and keep posting.

  • Sound and Code Creations LLC

    Thanks for the post, very helpful.

    Have you noticed longer loading times with the custom subclass approach? I added Chalkduster font to my app and it caused the initial load to increase to 3 to 4 sec and some of my screens within the app to take similar time. Without the custom font it was much faster.

    Thanks,

  • Karunakar bandikatla

    Thank you so much. It worked :)

  • Karim

    Hi nice post done by you. Its great work. I tried this by ENGLISH it works fine. But i am trying to use for ARABIC font styles it does not work. Do you have any idea in ARABIC font styles please help me.

  • Gabriel

    - (void)drawTextInRect:(CGRect)rect
    {
    [self setFont:[UIFont fontWithName: @"DINCond-Medium" size: self.font.pointSize]];
    [self setTextColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"FontBackground.png"]]];

    [super drawTextInRect:rect];
    }

  • John

    Your bit at the end about iterating through the fonts was excellent. I was having a rough time and then I realized I should check to see if the font was named something other than the name of the file I added and it happened that it was slightly different.

    Thanks!

  • Parashuram Bandaram

    Thank your for the post. This will works while we add Font in Resource folder and info.plist statically. But my case fonts will come dyanamically from server. So in runtime I need to save in Resource folder and edit the info.plist. This also I done for Label using Fontlabel lybrary. But I need for textfield. If have any idea kindly help me.

  • Tarmo Lehtpuu

    I haven’t tried that, but if you do please let me know :)

  • Tarmo Lehtpuu

    It’s a bit hard to explain in words, but basically the properties from your header file that have @IBOutlet in front of them will show up in IB (most likely when clicking on File’s Owner). With File’s Owner highlighted, the outlets should be visible and you can drag “noodles” to/from UI components.

    Hope this helps :)

Liked this post?

There’s more where that came from. Follow us on Facebook, Twitter or subscribe to our RSS feed to get all the latest posts immediately.