10
votes

To my knowledge, the default font of iOS 7 is Helvetica Neue UltraLight, which is a lot thinner compared to its bold predecessor. To provide a consistent design and make my forthcoming apps look the same across all common iOS versions, I'd like to apply Helvetica Neue UltraLight as the default (primary) font of the app.

Gladly, this "new font" is available since iOS version 5.0, so it's already supported by versions prior to iOS 7. Sadly, the only way I figured out to use it, is to manually call [UIFont fontWithName:@"HelveticaNeue-UltraLight" size:size] on each UIView's font, which is tedious and error-prone to inconsistency.

So my question is, what is your way to do this or how do you handle this design change?

4
One thing to consider - iOS 6 users want apps that look like iOS 6. iOS 7 users will want apps to look like iOS 7. Personally, I think your app should use a default iOS 6 font when run under iOS 6. Same with icons. But that is just one opinion.rmaddy
I think it's a good idea to assimilate elements of iOS7 into a current iOS 6 app - but only, if the overall "theme" allows this. This way there not necessarily needs to be a completely different version for 6 and 7, at least not until the majority of users have installed 7.brainray
@rmaddy : iOS7 is a huge jump. At this point I think iOS6 users are going to be lucky to have any support at all, much less an app tailored to run in iOS7 but also look right in iOS6.Kendall Helmstetter Gelner
Don't be sorry! I would love to have a better solution as well. These types of solutions are hacks, but when there is no other solution, a hack will do.Leo Natan
From the Interface Guidelines: "An app uses the same app icon in all versions of iOS that it supports. If you decide to redesign the app icon for the iOS 7 version of your app, the new icon should replace the old one even if the app displays different UI in different versions of iOS.". Maybe the same idea should be used with other elements!Peter V

4 Answers

18
votes

Here is the Objective-C Runtime solution:

@interface UIFont (CustomSystemFont)

+ (UIFont *)ln_systemFontOfSize:(CGFloat)fontSize;
+ (UIFont *)ln_boldSystemFontOfSize:(CGFloat)fontSize;
+ (UIFont *)ln_italicSystemFontOfSize:(CGFloat)fontSize;

@end
@implementation UIFont (CustomSystemFont)

+ (void)load
{
    Method orig = class_getClassMethod([UIFont class], @selector(systemFontOfSize:));
    Method swiz = class_getClassMethod([UIFont class], @selector(ln_systemFontOfSize:));
    method_exchangeImplementations(orig, swiz);

    orig = class_getClassMethod([UIFont class], @selector(boldSystemFontOfSize:));
    swiz = class_getClassMethod([UIFont class], @selector(ln_boldSystemFontOfSize:));
    method_exchangeImplementations(orig, swiz);

    orig = class_getClassMethod([UIFont class], @selector(italicSystemFontOfSize:));
    swiz = class_getClassMethod([UIFont class], @selector(ln_italicSystemFontOfSize:));
    method_exchangeImplementations(orig, swiz);
}

+ (UIFont *)ln_systemFontOfSize:(CGFloat)fontSize
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
        //Call original implementation.
        return [self ln_systemFontOfSize:fontSize];
    }

    return [UIFont fontWithName:@"HelveticaNeue" size:fontSize];
}

+ (UIFont *)ln_boldSystemFontOfSize:(CGFloat)fontSize
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
        //Call original implementation.
        return [self ln_systemFontOfSize:fontSize];
    }

    return [UIFont fontWithName:@"HelveticaNeue-Medium" size:fontSize];
}

+ (UIFont *)ln_italicSystemFontOfSize:(CGFloat)fontSize
{
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
        //Call original implementation.
        return [self ln_systemFontOfSize:fontSize];
    }

    return [UIFont fontWithName:@"HelveticaNeue-Italic" size:fontSize];
}

@end

What I do in this example is replace the three system font methods with my own and test to see if the system version is 7 or up. If it is, I use the original methods, otherwise return a font of my choosing (in this case Helvetica Neue with UltraLight weight for regular and italic requests, and Medium weight for bold requests).

This works for everything generated in code, including system created views. It does not work when loading views from Xib and Storyboard files, because the fonts are hardcoded in the NIB file itself. Use the font picker to choose the font you need.

11
votes

Why not just use the appearance API?

 [[UILabel appearance] setFont:[UIFont fontWithName:@"YourFontName" size:14.0]];

UIAppearance API

4
votes

Without breaking NDA by being specific about the method names - why not declare a category on UIFont to mimic the new methods for dynamic type?

3
votes

For those looking for a solution in storyboards, I had some success opening the storyboard file in a text editor and doing a search/replace. You have to catch each type of font you want to change (e.g. Bold/Italic), but I was able to replace the standard system font with HelveticaNeue UltraLight by replacing:

key="fontDescription" type="system"

with

key="fontDescription" name="HelveticaNeue-UltraLight" family="Helvetica Neue"

For bold, you would replace:

key="fontDescription" type="boldSystem"

I chose to replace my bold fonts with the same UltraLight font, but for those wanting a "bold" treatment you could choose "HelveticaNeue-Thin".

I recommend using version control or making a backup copy of your file before doing this though!