# Objective-C runtime in practice: changing fonts throughout an interface

Language: en
Canonical: [Objective-C runtime in practice: changing fonts throughout an interface](<https://allluckly.cn/en/journal/2016-05-04-objective-c-runtime-in-practice-changing-fonts-throughout-an-interface/>)
中文：[中文 HTML](<https://allluckly.cn/%E6%8A%95%E7%A8%BF/tuogao43>)
English: [English HTML](<https://allluckly.cn/en/journal/2016-05-04-objective-c-runtime-in-practice-changing-fonts-throughout-an-interface/>)
Published: 2016-05-04T00:00:00+08:00
Modified: 2026-10-23T10:34:14+08:00
Author: HenryCheng

Starts with registering a custom font and finding its name, then uses Objective-C runtime techniques to replace interface fonts. It discusses the differences between controls created in code and those loaded from a storyboard when applying a common setting.

Originally credited to HenryCheng; edited and archived by Bison.

[Source listed in the original](<http://www.jianshu.com/p/b9fdd17c525e>)

English translation of the [Chinese original](<https://allluckly.cn/%E6%8A%95%E7%A8%BF/tuogao43>), translated on 2026-10-23. The article body uses automated translation; app descriptions, historical reading notes and video subtitles receive separate editorial checks. Original publication dates, attribution, code and version notes are retained.

**Before you read** This technical note dates from 2015–2017. The examples have not been rerun as part of this archive update. Read API, dependency and tool details in the context of the original publication date.

Editor: [Bison](<https://allluckly.cn/en/>)  
 Contributor: [HenryCheng](<http://www.jianshu.com/p/b9fdd17c525e>)

Busy, busy, busy! It has been a long time since I last blogged. My days have been packed, and when I get home I am too tired to write, so I just read a little in bed. Our company has a major launch event in May, and we need to stabilize the release and improve the interface beforehand. There is plenty of detailed work to do.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/1.jpg>)

The latest version was submitted a couple of days ago, leaving me a little spare time, so I am sharing the runtime-based method for changing fonts in one step that I mentioned earlier. You might ask: is changing a font not simply a matter of replacing its name? Take a seat, grab a snack, and let me explain.

## 1. Preparation

Create a project named ChangeFont. I picked a font file called loveway.ttf and dragged it in. The project structure looks roughly like this:

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/2.png>)

For now, drag a label and a button onto the storyboard and add constraints, like this:

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/3.png>)

Yes, it is that simple. Run it.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/4.png>)

It displays normally. Next, change the font.

## 2. Change the font

We already added loveway.ttf. Now configure the plist: add a row named Fonts provided by application, then put the font filename in an item.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/5.png>)

Finally, verify that we really have added it.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/6.png>)

You may be impatient to change the font now. Here is how:

```
//
//  ViewController.m
//  ChangeFont
//
//  Created by HenryCheng on 16/4/27.
//  Copyright © 2016年 HenryCheng. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *myLabel;
@property (weak, nonatomic) IBOutlet UIButton *myButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    _myLabel.font = [UIFont fontWithName:@"loveway.ttf" size:17.0f];
    _myButton.titleLabel.font = [UIFont fontWithName:@"loveway" size:17.0f];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
```

Run it… oh no! Nothing changed; it still looks the same.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/7.gif>)

I must be doing something wrong, so I searched Baidu, although I usually use Google. Indeed, this approach was incorrect.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/8.jpg>)

I changed approach: first find the font's actual name. Like this—change the code to:

```
- (void)viewDidLoad {
    [super viewDidLoad];

    for(NSString *familyName in [UIFont familyNames]){
        NSLog(@"Font FamilyName = %@",familyName); //*输出字体族科名字

        for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
            NSLog(@"\t%@",fontName);         //*输出字体族科下字样名字
        }
    }
    _myLabel.font = [UIFont fontWithName:@"loveway.ttf" size:17.0f];
    _myButton.titleLabel.font = [UIFont fontWithName:@"loveway" size:17.0f];
}
```

Run it and inspect the console.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/9.png>)

What is this? I do not know the name of the font I just added. How am I supposed to find it?

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/10.jpg>)

Then I thought of a solution: create another project without loveway.ttf, print the font list, and compare the entries. The extra entry must be the font! Bingo—after a little work, I found FZLBJW–GB1-0. Time to try it.

```
- (void)viewDidLoad {
    [super viewDidLoad];
    /*
    for(NSString *familyName in [UIFont familyNames]){
        NSLog(@"Font FamilyName = %@",familyName); //输出字体族科名字

        for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
            NSLog(@"\t%@",fontName);         //输出字体族科下字样名字
        }
    }
     */
    _myLabel.font = [UIFont fontWithName:@"FZLBJW--GB1-0" size:17.0f];
    _myButton.titleLabel.font = [UIFont fontWithName:@"FZLBJW--GB1-0" size:17.0f];
}
```

Run it; the result follows.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/11.png>)

Result after changing the font

OK! It works. The result is a little awkward, but we achieved the effect—not bad.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/12.gif>)

At this point, the basic font change is complete.

## 3. A simple way to find a font name

We found FZLBJW–GB1-0 by comparing font lists above, but there is an easier way. Find the ttf in Finder and double-click it. Double-clicking it in Xcode does not have this effect. The system opens it in Apple's Font Book, as shown below.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/13.png>)

We can now see the font-family name, FZLiBian-S02S. Search for that family in the console output listing all fonts to find the specific font name.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/14.png>)

This is much simpler than the earlier approach.

## 4. Further considerations

The example above changes fonts successfully, but it raises a question. There are only two simple controls here; what if there are many? You could apply the same method one by one, which is manageable for controls created in code. But with xibs, must you create outlets for every otherwise unneeded display-only label or button just to change the font? That would be inefficient, especially in a large, partly completed project. This approach clearly will not scale.  
 This uses the runtime methods class\_addMethod, class\_replaceMethod, and method\_exchangeImplementations together with the behavior of + (void)load. I will discuss + (void)load later; if it is unfamiliar, you can also look it up first. Here is the code:

```
//
//  UILabel+FontChange.m
//  LiquoriceDoctorProject
//
//  Created by HenryCheng on 15/12/7.
//  Copyright © 2015年 iMac. All rights reserved.
//

#import "UILabel+FontChange.h"
#import <objc/runtime.h>

#define CustomFontName @"FZLBJW--GB1-0"

@implementation UILabel (FontChange)

+ (void)load {
    //方法交换应该被保证，在程序中只会执行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //获得viewController的生命周期方法的selector
        SEL systemSel = @selector(willMoveToSuperview:);
        //自己实现的将要被交换的方法的selector
        SEL swizzSel = @selector(myWillMoveToSuperview:);
        //两个方法的Method
        Method systemMethod = class_getInstanceMethod([self class], systemSel);
        Method swizzMethod = class_getInstanceMethod([self class], swizzSel);

        //首先动态添加方法，实现是被交换的方法，返回值表示添加成功还是失败
        BOOL isAdd = class_addMethod(self, systemSel, method_getImplementation(swizzMethod), method_getTypeEncoding(swizzMethod));
        if (isAdd) {
            //如果成功，说明类中不存在这个方法的实现
            //将被交换方法的实现替换到这个并不存在的实现
            class_replaceMethod(self, swizzSel, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
        } else {
            //否则，交换两个方法的实现
            method_exchangeImplementations(systemMethod, swizzMethod);
        }

    });
}

- (void)myWillMoveToSuperview:(UIView *)newSuperview {

    [self myWillMoveToSuperview:newSuperview];
//    if ([self isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
//        return;
//    }
    if (self) {
        if (self.tag == 10086) {
            self.font = [UIFont systemFontOfSize:self.font.pointSize];
        } else {
            if ([UIFont fontNamesForFamilyName:CustomFontName])
                self.font  = [UIFont fontWithName:CustomFontName size:self.font.pointSize];
        }
    }
}

@end
```

Without adding any code, it looks like this:

```
//
//  ViewController.m
//  ChangeFont
//
//  Created by HenryCheng on 16/4/27.
//  Copyright © 2016年 HenryCheng. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *myLabel;
@property (weak, nonatomic) IBOutlet UIButton *myButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

//    for(NSString *familyName in [UIFont familyNames]){
//        NSLog(@"Font FamilyName = %@",familyName); //输出字体族科名字
//
//        for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
//            NSLog(@"\t%@",fontName);         //输出字体族科下字样名字
//        }
//    }

//    _myLabel.font = [UIFont fontWithName:@"FZLBJW--GB1-0" size:17.0f];
//    _myButton.titleLabel.font = [UIFont fontWithName:@"FZLBJW--GB1-0" size:17.0f];
//    _myLabel.tag = 10086;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
```

Run

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/15.png>)

We can see that the font has changed.  
 What if some views should change font and others should not? A simple approach is to use a tag. For example, I assign a label the arbitrary tag 10086 to exempt it from the font change.

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/16.png>)

Result when run

![1](<https://allluckly.cn/images/blog/tuogao/tougao43/17.png>)

### Note:

1. For a control created in code whose font should remain unchanged, set its tag to 10086 when creating it.  
 2. One line in the code above is commented out:

```
//    if ([self isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
//        return;
//    }
```

This line was originally used to leave button-title fonts unchanged. Decide which control types should change and which should not. To preserve button fonts, uncomment this line.  
 3. For a control created in a xib whose font should remain unchanged, set its tag to 10086 in the xib. Do not wait until - (void)viewDidLoad after loading. This is again due to the behavior of + (void)load.

Before a program's main function runs, after its libraries load into the runtime, the runtime invokes +load on the classes and categories added to it. You can easily verify this with log statements.  
 If both a superclass and subclass have +load methods invoked, the superclass always runs first. The system handles this automatically; the subclass does not need to call \[super load\] explicitly. This is only a brief explanation. Consult the official documentation for more detail.

## 5. Finally

The project's comments explain the code clearly, so I will not repeat them here. Leave a comment if something is unclear. Usage is simple: drag UILabel+FontChange.h and UILabel+FontChange.m into your project. For more fonts, visit [Download fonts](<http://www.webpagepublicity.com/free-fonts.html>). All the code is available at [Here,](<https://github.com/Loveway/HWChangeFont>)Download.  
 I have been studying Swift and taking notes lately. I will share some Swift tips later.  
 Finally, please leave any suggestions or corrections in the comments. If you like this or find it useful, give it a star. Thank you!

---

Recommended reading: [Rich text with hyperlinks on iOS](<https://allluckly.cn/en/journal/2016-04-29-rich-text-with-hyperlinks-on-ios/>)

