忙忙忙!!!好久沒寫部落格了,前段時間實在是每天滿滿的,回去了累了也不想寫了,只是躺床上看一會東西。最近公司要在5月份舉辦個大型的釋出會,所以在這之前要把版本穩定,介面提升,所以有很多細活要幹。
不過,趁前兩天版本剛提交上線,這兩天稍微閒一點,就把之前說的利用runtime
一鍵改變字型的方法分享出來。有人會說,改變字型不是很簡單嗎,我直接找到字型名替換一下不就好了?客官不要急,先坐下來吃點瓜子,聽我慢慢給你說來。
1、準備
我們新建一個專案名叫ChangeFont
,然後我就隨便找了個名叫loveway.ttf
的字型庫拖進去,裡面的工程目錄大概就是這樣的
現在我們就簡單的直接在storyboard
上拖了一個label
一個button
,約束好,像這樣
嗯,就這樣,很簡單,執行
好的顯示正常,沒什麼問題,接下來改變字型。
2、改變字型
我們之前已經把loveway.ttf
這個檔案拖進去了,現在在plist
檔案裡面配置一下。開啟plist
然後加入名為Fonts provided by application
的一行,在item
裡把我們的字型名字加進去
最後我們需要保證我們確確實實是加進來了
這個時候也許你已經迫不及待了,趕緊改字型,如下
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]; _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 12 13 |
- (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
,不管了,先試試看行不行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
![](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
這個方法後面會說,或者不懂得童鞋可以先查查資料),程式碼如下
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 49 50 51 52 53 54 55 56 57 58 |
// // 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 32 33 34 35 36 37 38 39 40 |
// // 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
一下吧,謝謝!