iOS修改字型

weixin_33670713發表於2017-05-07

一、目的
有些公司在專案開發中,可能應用自己定義的字型樣式,這樣就涉及了字型設定的方法了,今天在這裡用程式碼簡單演示一下,以備不時之需。
二、準備
新建一個工程ChangeFont,然後將一個DS-DIGII.TTF的字型庫拖工程中,裡面的工程目錄大概就是這樣的:

4999539-0882a9296cdb2675.png
目錄.png

接下來我們可以在ViewController類中建立一個UILabel來顯示字型樣式:

UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(100, 100, 160, 50);
label.backgroundColor = [UIColor yellowColor];
label.textAlignment = NSTextAlignmentCenter;
label.text = @"9876543210";
[self.view addSubview:label];

執行結果:


4999539-9d9c1a25e97e66ed.png
執行結果.png

三、改變字型
之前已經把DS-DIGII.TTF這個檔案拖進去了,現在在plist檔案裡面配置一下。開啟plist然後加入名為Fonts provided by application的一行,在item裡把字型名字加進去。(ps:帶字尾)

4999539-1b1018c31ad4081b.png
配置.png

在程式碼中更改字型,如下:
(ps:字型檔名稱不代表字型名稱,所以不能直接在程式碼中寫DS-DIGII.TTF檔名)

首先需要找出字型名稱,遍歷一下:

for(NSString *familyName in [UIFont familyNames]){
        NSLog(@"Font FamilyName = %@",familyName); // 輸出字型族科名字
        for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
            NSLog(@"\t%@",fontName); // 輸出字型族科下字樣名字
        }
    }

最後找出了相對於沒有新增這個字型的工程多出的字型就是本次新增的字型了
結果:
// Font FamilyName = DS-Digital
// 2017-05-07 13:31:44.639 ChangeFont[9315:66825327]    DS-Digital-Italic

換個姿勢:
據說,在 Finder 裡面找到這個TTF,雙擊開啟,也能看到這個字型名稱:


4999539-4d599d16adb39786.png
換個姿勢.png

接下來測試:

UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(100, 100, 160, 50);
label.backgroundColor = [UIColor yellowColor];
label.textAlignment = NSTextAlignmentCenter;
label.text = @"9876543210";
label.font = [UIFont fontWithName:@"DS-Digital" size:16.0f];
[self.view addSubview:label];
4999539-ee428acc0bc2547c.png
好了.png

OK!效果改變字型在這裡就簡單的實現了。

四、深思
有沒有感覺上面的方法很lou,控制元件多了就吐血了,其實可以利用runtime的class_addMethod、class_replaceMethod、method_exchangeImplementations這幾個方法實現,程式碼如下:

class_getInstanceMethod得到類的例項方法
class_getClassMethod得到類的類方法

#import <UIKit/UIKit.h>

@interface UILabel (FontChange)

@end
#import "UILabel+FontChange.h"
#import <objc/runtime.h>

#define CustomFontName @"DS-Digital"
@implementation UILabel (FontChange)

+ (void)load {
    // 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];
    // 不改變button的title字型設定的,在這裡你可以判斷那種型別的改哪種不改,比如說你不想改button的字型,把這一句解註釋即可
    // if ([self isKindOfClass:NSClassFromString(@"UIButtonLabel")]) {
    //     return;
    // }
    if (self) {
        if (self.tag == 000000) {
            self.font = [UIFont systemFontOfSize:self.font.pointSize];
        } else {
            if ([UIFont fontNamesForFamilyName:CustomFontName])
                self.font  = [UIFont fontWithName:CustomFontName size:self.font.pointSize];
        }
    }
}

@end
然後不加任何程式碼如下:
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(100, 100, 160, 50);
label.backgroundColor = [UIColor yellowColor];
label.textAlignment = NSTextAlignmentCenter;
label.text = @"9876543210";
// label.tag = 000000;
// label.font = [UIFont fontWithName:@"DS-Digital" size:16.0f];
[self.view addSubview:label];
這樣就可以實現了

------整理

相關文章