【iOS】利用runtime替換方法實(shí)現(xiàn)對不同機(jī)型字體大小的適配

場景描述

如果在你的工程代碼已經(jīng)寫好了,面臨交貨,突然這個時候產(chǎn)品說,要讓6和6P的字體大小不一樣...233這個時候,就尷尬了。不過對于你界面上的控件是純代碼創(chuàng)建的,這個時候,嘿嘿,就有很好的方法了,通過runtime替換系統(tǒng)字體大方法systemFontOfSize:方法就能很快實(shí)現(xiàn)了。但是這樣也有個缺陷,如果是用xib創(chuàng)建的控件,并設(shè)置的字體大小,嘿嘿。那可有得搞了。需要手動在awakeFromNib方法里面手動設(shè)置(哭臉).

runtime替換方法

對于runtime的內(nèi)容,就不再這里細(xì)說了,runtime能實(shí)現(xiàn)的東西很多,用runtime能實(shí)現(xiàn)很多裝逼特技。

實(shí)現(xiàn)步驟

  • 先定義好不同機(jī)型的宏
  • 給UIFont添加一個分類
  • 在這個分類里面實(shí)現(xiàn)自定義的設(shè)置字體的方法
  • 重載系統(tǒng)的load方法,實(shí)現(xiàn)自定義方法和系統(tǒng)方法的替換。

1.新建UIFont的分類

這個步驟就不細(xì)說了,也很簡單。就是command + N, 然后選擇對應(yīng)選項(xiàng)。

2.在分類中添加不同機(jī)型的宏,以及不同機(jī)型上的字體號數(shù)的對應(yīng)改變量。

// 設(shè)備
#define IS_IPAD     [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad
#define IS_IPHONE   [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone
#define IS_IPHONE_4 (fabs((double)[[UIScreen mainScreen] bounds].size.height - (double )480) < DBL_EPSILON )
#define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen] bounds].size.height - (double )568) < DBL_EPSILON )
#define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen] bounds].size.height - (double )667) < DBL_EPSILON )
#define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen] bounds].size.height - (double )960) < DBL_EPSILON )

// 放大的字號數(shù)
#define IPHONE6_INCREMENT 2
#define IPHONE6PLUS_INCREMENT 3

這里的放大字號數(shù)的意思是,如果設(shè)置的系統(tǒng)字體大小為15,那么在4、5上面的大小就是15,而在6上就增加2,即17,在6P上就增加3,即18。具體改變多少根據(jù)需求設(shè)定。這個為了顯示出區(qū)別,暫且改為10便于觀察。

3. 添加自定義方法,實(shí)現(xiàn)不同機(jī)型不同字體

+ (UIFont *)adjustFont:(CGFloat)fontSize{
    
    UIFont * newFont = nil;
    
    if (IS_IPHONE_6) {
        newFont = [UIFont adjustFont:fontSize + IPHONE6_INCREMENT];
    }else if (IS_IPHONE_6_PLUS){
        newFont = [UIFont adjustFont:fontSize + IPHONE6PLUS_INCREMENT];
    }else{
        newFont = [UIFont adjustFont:fontSize];
    }
    return newFont;
}

4.利用runtime交換系統(tǒng)的systemFontOfSize:方法和自定義方法

  • 要使用runtime,那么就需要導(dǎo)入相應(yīng)的頭文件:#import <objc/runtime.h>
  • 然后在+(void)load方法中實(shí)現(xiàn)替換。(load方法在該分類到內(nèi)存的時候調(diào)用,比init方法先調(diào)用)
  • 獲取類方法用class_getClassMethod,獲取對象方法用class_getInstanceMethod
+(void)load{
    
    // 獲取交換后的方法
    Method newMethod = class_getClassMethod([self class], @selector(adjustFont:));
    
    // 獲取替換前的方法
    Method method = class_getClassMethod([self class], @selector(systemFontOfSize:));
    
    // 交換
    method_exchangeImplementations(newMethod, method);
}

5. 測試

在VC里面添加一個label并設(shè)置字體大小,分別用5s和6運(yùn)行查看。

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UILabel * label = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 200, 50)];
    label.font = [UIFont systemFontOfSize:15];
    label.text = @"字體測試";
    [self.view addSubview:label];
}

效果:


5s和6的字體大小不一樣

6.總結(jié)

雖然這樣能實(shí)現(xiàn),但是systemFontOfSize方法只是用存代碼寫的控件的時候用啊 如果是用xib寫的控件,并設(shè)置了字體就不行了。那如果是用xib寫的UI,有什么好的方法呢?

  • 提供了一種思路,在VC里面重寫layoutSubViews方法,遞歸遍歷所有的控件,設(shè)置font。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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