iOS中利用 runtime 一鍵改變字體

一、準備html

咱們新建一個項目名叫ChangeFont,而後我就隨便找了個名叫loveway.ttf的字體庫拖進去,裏面的工程目錄大概就是這樣的git

571495-91a43c0fac5f91e4.jpg

目錄github

如今咱們就簡單的直接在storyboard上拖了一個label一個button,約束好,像這樣web

571495-d567ca72aadb692b.jpg

storyboardswift

嗯,就這樣,很簡單,運行app

571495-e81ac83f048a9545.jpg

運行結果ide

好的顯示正常,沒什麼問題,接下來改變字體。函數

二、改變字體字體

咱們以前已經把loveway.ttf這個文件拖進去了,如今在plist文件裏面配置一下。打開plist而後加入名爲Fonts provided by application的一行,在item裏把咱們的字體名字加進去this

571495-f3a34a72dd21beaa.jpg

plist

最後咱們須要保證咱們確確實實是加進來了

571495-89647ae861ac1ba8.jpg

phases

這個時候也許你已經火燒眉毛了,趕忙改字體,以下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

//

//  ViewController.m

//  ChangeFont

//

#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

運行。。。oh no !怎麼沒變,仍是原來的樣子?!

確定是姿式不對,因而百度了一下(雖然我通常都用谷歌),的確這種方法不對。

因而改變思路,先找出字體的名字,Like this,代碼改爲這樣

1

2

3

4

5

6

7

8

9

10

11

- (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];

}

運行一看控制檯

571495-0aa0ce498e8e115f.jpg

輸出的字體名稱部分截圖

這什麼鬼,我哪知道我剛加進去的字體名稱是什麼,這咋找

因而想出來個辦法,再建一個工程,不加入loveway.ttf這個字體,打印出來,一個個對比,多的那個不就是了嗎!bingo,因而花了一會功夫終於找出來了,是FZLBJW--GB1-0,無論了,先試試看行不行

1

2

3

4

5

6

7

8

9

10

11

12

13

14

![](http://upload-images.jianshu.io/upload_images/571495-b0d97825e5d33a8a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

- (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];

}

運行,結果以下

571495-c438612edb9e919e.png

改變字體後的運行結果

OK!達到效果了,雖然有點挫,可是效果達到了,還不錯。

到這裏,基本的改變字體效果已達到。

三、查找字體的一種簡單的方法

在上面咱們能夠看到,經過對比的方法找到了FZLBJW--GB1-0這個名字,這裏,有一種簡單的方法,咱們在 Finder 裏面找到這個ttf,雙擊打開(在Xcode裏面雙擊打開沒效果),這時候系統就會用蘋果自帶的字體冊打開,以下:

571495-6f429dd17e7f8a8e.jpg

使用字體冊打開.rtf

這樣咱們就能夠看到了這個字體的族科名字,咱們看到的是FZLiBian-S02S,因而咱們在剛纔輸出所有字體名的控制檯搜索一下這個族科名,就能夠知道具體的字體名了

571495-71dbd7f8d809bef6.jpg

搜索FZLiBian-S02S

這樣就比上面簡單多了。

四、進一步的思考

上面例子中簡單的說了一下改變字體的方法,雖然成功了,可是咱們不得不思考一下。上面只是兩個簡單的控件,那麼我要是有一堆控件怎麼辦?或者你能夠說我也可用這種方法一個個加,你要是純代碼寫的還好,你要是xib寫的,難道還要把一個個無用的只是顯示一下的label或者button拉出來這樣寫嗎?這樣的話,效率確定會很是低,尤爲是那些寫到一半的大工程,感受這種方法確定是行不通的。

這裏利用runtime的class_addMethod、class_replaceMethod、method_exchangeImplementations這幾個方法,而後根據+ (void)load這個方法的特性實現(關於+ (void)load這個方法後面會說,或者不懂得童鞋能夠先查查資料),代碼以下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

//

//  UILabel+FontChange.m

//  LiquoriceDoctorProject

//

//  Created by HenryCheng on 15/12/7.

//  Copyright ? 2015 iMac. All rights reserved.

//

#import "UILabel+FontChange.h"

#import #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

而後不加任何代碼以下

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

//

//  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

運行

571495-c438612edb9e919e (1).png

咱們能夠看到字體改變了。

若是有人說我有的想改變字體有的不想改變字體怎麼辦,我這裏有個簡單的辦法就是設置tag,好比我設置label的tag爲10086(隨便起的),就讓他字體不改變

1462338192307160.png

運行結果

571495-67c22bdfcd9f68b9.png

注意:

一、若是你是代碼寫控件,你不想改變字體,你只需在建立的時候設置tag爲10086

二、上面代碼中註釋了一行

1

2

3

//if ([self isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {

//      return;

// }

這個是當時寫的時候不改變button的title字體設置的,在這裏你能夠判斷那種類型的改哪一種不改,好比說你不想改button的字體,把這一句解註釋便可

三、若是你是xib拉的控件,你不想改變字體,你必須在xib界面設置tag爲10086,不可加載完畢後在- (void)viewDidLoad裏面設置,這仍是由於+ (void)load這個方法

在一個程序(main函數)運行以前,所用到的庫被加載到runtime以後,被添加到的runtime系統的各類類和category的+load方法就被調用;(關於這點很容易經過打印語句來驗證);

若是父類和子類的+load方法都被調用,父類的調用必定在子類以前,這是系統自動完成的,子類+load中不必顯式調用[super load];;

這裏只是簡單的說一下,具體不理解的能夠翻翻官方文檔

五、最後

關於代碼的解釋,在工程裏都已經註釋的很是清楚了,這裏就很少說了,不清楚的童鞋能夠給我留言。具體用法很簡單,你只須要將UILabel+FontChange.h和UILabel+FontChange.m拉進你的工程便可。

須要下載更多字體的能夠在字體庫下載,全部的代碼均可以在這裏下載。

最近在看swift,作了一下筆記,後面會爲你們分享總結的一些swift tips。

最後,若是你有什麼建議或者指正的地方請給我留言,若是喜歡或者對你有幫助的話,就請star一下吧,謝謝!

相關文章
相關標籤/搜索