iOS中利用 runtime 一鍵改變字型

來源:互聯網
上載者:User

標籤:

http://www.cocoachina.com/ios/20160504/16109.html

 

本文為投稿文章,HenryCheng(簡書)

最近公司要在5月份舉辦個大型的發布會,所以在這之前要把版本穩定,介面提升,所以有很多細活要幹。不過,趁前兩天版本剛提交上線,這兩天稍微閑一點,就把之前說的利用runtime一鍵改變字型的方法分享出來。有人會說,改變字型不是很簡單嗎,我直接找到字型名替換一下不就好了?客官不要急,先坐下來吃點瓜子,聽我慢慢給你說來。

1、準備

我們建立一個項目名叫ChangeFont,然後我就隨便找了個名叫loveway.ttf的字型庫拖進去,裡面的工程目錄大概就是這樣的

目錄

現在我們就簡單的直接在storyboard上拖了一個label一個button,約束好,像這樣

storyboard

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

運行結果

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

2、改變字型

我們之前已經把loveway.ttf這個檔案拖進去了,現在在plist檔案裡面配置一下。開啟plist然後加入名為Fonts provided by application的一行,在item裡把我們的字型名字加進去

plist

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

phases

這個時候也許你已經迫不及待了,趕緊改字型,如下

1234567891011121314151617181920212223 ////  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 !怎麼沒變,還是原來的樣子?!

肯定是姿勢不對,於是百度了一下(雖然我一般都用Google),的確這種方法不對。

於是改變思路,先找出字型的名字,Like this,代碼改成這樣

1234567891011 - (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,不管了,先試試看行不行

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

運行,結果如下

改變字型後的運行結果

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

到這裡,基本的改變字型效果已達到。

3、尋找字型的一種簡單的方法

在上面我們可以看到,通過對比的方法找到了FZLBJW--GB1-0這個名字,這裡,有一種簡單的方法,我們在 Finder 裡面找到這個ttf,雙擊開啟(在Xcode裡面雙擊開啟沒效果),這時候系統就會用蘋果內建的字型冊開啟,如下:

使用字型冊開啟.rtf

這樣我們就可以看到了這個字型的族科名字,我們看到的是FZLiBian-S02S,於是我們在剛才輸出全部字型名的控制台搜尋一下這個族科名,就可以知道具體的字型名了

搜尋FZLiBian-S02S

這樣就比上面簡單多了。

4、進一步的思考

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

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

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

然後不加任何代碼如下

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

運行

我們可以看到字型改變了。

如果有人說我有的想改變字型有的不想改變字型怎麼辦,我這裡有個簡單的辦法就是設定tag,比如我設定label的tag為10086(隨便起的),就讓他字型不改變

運行結果

注意:

1、如果你是代碼寫控制項,你不想改變字型,你只需在建立的時候設定tag為10086

2、上面代碼中注釋了一行

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

這個是當時寫的時候不改變button的title字型設定的,在這裡你可以判斷那種類型的改哪種不改,比如說你不想改button的字型,把這一句解注釋即可

3、如果你是xib拉的控制項,你不想改變字型,你必須在xib介面設定tag為10086,不可載入完畢後在- (void)viewDidLoad裡面設定,這還是因為+ (void)load這個方法

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

如果父類和子類的+load方法都被調用,父類的調用一定在子類之前,這是系統自動完成的,子類+load中沒必要顯式調用[super load];;

這裡只是簡單的說一下,具體不理解的可以翻翻官方文檔

5、最後

關於代碼的解釋,在工程裡都已經注釋的非常清楚了,這裡就不多說了,不清楚的童鞋可以給我留言。具體用法很簡單,你只需要將UILabel+FontChange.h和UILabel+FontChange.m拉進你的工程即可。

需要下載更多字型的可以在字型庫下載,所有的代碼都可以在這裡下載。

最近在看swift,做了一下筆記,後面會為大家分享總結的一些swift tips。

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

iOS中利用 runtime 一鍵改變字型

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.