iOS中利用 runtime 一鍵改變字體

忙忙忙!@パ省驾凶!好久沒寫博客了,前段時間實在是每天滿滿的掷酗,回去了累了也不想寫了调违,只是躺床上看一會東西。最近公司要在5月份舉辦個大型的發(fā)布會泻轰,所以在這之前要把版本穩(wěn)定技肩,界面提升,所以有很多細活要干浮声。


不過虚婿,趁前兩天版本剛提交上線,這兩天稍微閑一點泳挥,就把之前說的利用runtime一鍵改變字體的方法分享出來然痊。有人會說,改變字體不是很簡單嗎屉符,我直接找到字體名替換一下不就好了剧浸?客官不要急锹引,先坐下來吃點瓜子,聽我慢慢給你說來唆香。

1嫌变、準備


我們新建一個項目名叫ChangeFont,然后我就隨便找了個名叫loveway.ttf的字體庫拖進去躬它,里面的工程目錄大概就是這樣的

目錄

現(xiàn)在我們就簡單的直接在storyboard上拖了一個label一個button腾啥,約束好,像這樣

storyboard

嗯虑凛,就這樣碑宴,很簡單软啼,運行

運行結(jié)果

好的顯示正常桑谍,沒什么問題,接下來改變字體祸挪。

2锣披、改變字體


我們之前已經(jīng)把loveway.ttf這個文件拖進去了,現(xiàn)在在plist文件里面配置一下贿条。打開plist然后加入名為Fonts provided by application的一行雹仿,在item里把我們的字體名字加進去

plist

最后我們需要保證我們確確實實是加進來了

phases

這個時候也許你已經(jīng)迫不及待了,趕緊改字體整以,如下

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

運行胧辽。。公黑。oh no 邑商!怎么沒變,還是原來的樣子


肯定是姿勢不對凡蚜,于是百度了一下(雖然我一般都用谷歌)人断,的確這種方法不對


于是改變思路,先找出字體的名字朝蜘,Like this恶迈,代碼改成這樣

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

運行一看控制臺

輸出的字體名稱部分截圖

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


于是想出來個辦法暇仲,再建一個工程,不加入loveway.ttf這個字體副渴,打印出來熔吗,一個個對比,多的那個不就是了嗎佳晶!bingo桅狠,于是花了一會功夫終于找出來了,是FZLBJW--GB1-0,不管了中跌,先試試看行不行

![](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];
}

運行咨堤,結(jié)果如下

改變字體后的運行結(jié)果

OK!達到效果了漩符,雖然有點挫一喘,但是效果達到了,還不錯



到這里嗜暴,基本的改變字體效果已達到凸克。

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


在上面我們可以看到闷沥,通過對比的方法找到了FZLBJW--GB1-0這個名字萎战,這里,有一種簡單的方法舆逃,
我們在 Finder 里面找到這個ttf蚂维,雙擊打開(在Xcode里面雙擊打開沒效果),這時候系統(tǒng)就會用蘋果自帶的字體冊打開路狮,如下

使用字體冊打開`.rtf`

這樣我們就可以看到了這個字體的族科名字虫啥,我們看到的是FZLiBian-S02S,于是我們在剛才輸出全部字體名的控制臺搜索一下這個族科名奄妨,就可以知道具體的字體名了

搜索`FZLiBian-S02S`

這樣就比上面簡單多了涂籽。

4、進一步的思考


上面例子中簡單的說了一下改變字體的方法砸抛,雖然成功了评雌,但是我們不得不思考一下。上面只是兩個簡單的控件锰悼,那么我要是有一堆控件怎么辦柳骄?或者你可以說我也可用這種方法一個個加,你要是純代碼寫的還好箕般,你要是xib寫的耐薯,難道還要把一個個無用的只是顯示一下的label或者button拉出來這樣寫嗎?這樣的話丝里,效率肯定會非常低曲初,尤其是那些寫到一半的大工程,感覺這種方法肯定是行不通的杯聚。
這里利用runtimeclass_addMethod臼婆、class_replaceMethodmethod_exchangeImplementations這幾個方法幌绍,然后根據(jù)+ (void)load這個方法的特性實現(xiàn)(關(guān)于+ (void)load這個方法后面會說颁褂,或者不懂得童鞋可以先查查資料)故响,代碼如下

//
//  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 {
    //方法交換應(yīng)該被保證,在程序中只會執(zhí)行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        //獲得viewController的生命周期方法的selector
        SEL systemSel = @selector(willMoveToSuperview:);
        //自己實現(xiàn)的將要被交換的方法的selector
        SEL swizzSel = @selector(myWillMoveToSuperview:);
        //兩個方法的Method
        Method systemMethod = class_getInstanceMethod([self class], systemSel);
        Method swizzMethod = class_getInstanceMethod([self class], swizzSel);
        
        //首先動態(tài)添加方法颁独,實現(xiàn)是被交換的方法彩届,返回值表示添加成功還是失敗
        BOOL isAdd = class_addMethod(self, systemSel, method_getImplementation(swizzMethod), method_getTypeEncoding(swizzMethod));
        if (isAdd) {
            //如果成功,說明類中不存在這個方法的實現(xiàn)
            //將被交換方法的實現(xiàn)替換到這個并不存在的實現(xiàn)
            class_replaceMethod(self, swizzSel, method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));
        } else {
            //否則誓酒,交換兩個方法的實現(xiàn)
            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

然后不加任何代碼如下

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

運行


我們可以看到字體改變了樟蠕。
如果有人說我有的想改變字體有的不想改變字體怎么辦,我這里有個簡單的辦法就是設(shè)置tag靠柑,比如我設(shè)置labeltag10086(隨便起的)寨辩,就讓他字體不改變


運行結(jié)果

注意:
1、如果你是代碼寫控件歼冰,你不想改變字體靡狞,你只需在創(chuàng)建的時候設(shè)置tag10086
2、上面代碼中注釋了一行

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

這個是當時寫的時候不改變buttontitle字體設(shè)置的停巷,在這里你可以判斷那種類型的改哪種不改耍攘,比如說你不想改button的字體榕栏,把這一句解注釋即可
3畔勤、如果你是xib拉的控件,你不想改變字體扒磁,你必須在xib界面設(shè)置tag10086庆揪,不可加載完畢后在- (void)viewDidLoad里面設(shè)置,這還是因為+ (void)load這個方法

  • 在一個程序(main函數(shù))運行之前妨托,所用到的庫被加載到runtime之后缸榛,被添加到的runtime系統(tǒng)的各種類和category的+load方法就被調(diào)用;(關(guān)于這點很容易通過打印語句來驗證)兰伤;
  • 如果父類和子類的+load方法都被調(diào)用内颗,父類的調(diào)用一定在子類之前,這是系統(tǒng)自動完成的敦腔,子類+load中沒必要顯式調(diào)用[super load];均澳;
    這里只是簡單的說一下,具體不理解的可以翻翻官方文檔

5符衔、最后

關(guān)于代碼的解釋找前,在工程里都已經(jīng)注釋的非常清楚了,這里就不多說了判族,不清楚的童鞋可以給我留言躺盛。具體用法很簡單,你只需要將UILabel+FontChange.hUILabel+FontChange.m拉進你的工程即可形帮。
需要下載更多字體的可以在 字體庫下載槽惫,所有的代碼都可以在 這里下載周叮。
最近在看swift,做了一下筆記界斜,后面會為大家分享總結(jié)的一些swift tips则吟。
最后,如果你有什么建議或者指正的地方請給我留言锄蹂,如果喜歡或者對你有幫助的話氓仲,就請star一下吧,謝謝得糜!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末敬扛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子朝抖,更是在濱河造成了極大的恐慌啥箭,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件治宣,死亡現(xiàn)場離奇詭異急侥,居然都是意外死亡,警方通過查閱死者的電腦和手機侮邀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門坏怪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绊茧,你說我怎么就攤上這事铝宵。” “怎么了华畏?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵鹏秋,是天一觀的道長。 經(jīng)常有香客問我亡笑,道長侣夷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任仑乌,我火速辦了婚禮百拓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘绝骚。我一直安慰自己耐版,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布压汪。 她就那樣靜靜地躺著粪牲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪止剖。 梳的紋絲不亂的頭發(fā)上腺阳,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天落君,我揣著相機與錄音,去河邊找鬼亭引。 笑死绎速,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的焙蚓。 我是一名探鬼主播纹冤,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼购公!你這毒婦竟也來了萌京?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤宏浩,失蹤者是張志新(化名)和其女友劉穎知残,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體比庄,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡求妹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了佳窑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片制恍。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖华嘹,靈堂內(nèi)的尸體忽然破棺而出吧趣,到底是詐尸還是另有隱情法竞,我是刑警寧澤耙厚,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站岔霸,受9級特大地震影響薛躬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜呆细,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一型宝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧絮爷,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至柜蜈,卻和暖如春仗谆,著一層夾襖步出監(jiān)牢的瞬間指巡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工隶垮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留藻雪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓狸吞,卻偏偏與公主長得像勉耀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蹋偏,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 參考鏈接:http://www.cocoachina.com/ios/20160504/16109.html
    Maple_chang閱讀 337評論 0 0
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,181評論 25 707
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉瑰排,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,721評論 0 9
  • 清晨路過秀湖公園,園中無人暖侨,岸柳倒影湖中椭住,微風(fēng)吹過,隨波蕩漾字逗,青翠可愛京郑。 坐在湖邊,滿面春風(fēng)葫掉,我也一身無塵些举。 ...
    天許天許閱讀 591評論 1 1
  • “想聽你說一個你懷念的親密時刻户魏。 譬如兩人分一顆煙抽、突然從后面的抱住挪挤、穿他的襯衫用他的香水叼丑、或者只是每一次都幫你...
    missdora閱讀 297評論 0 0