最近在项目中,被要求将系统的苹方体全部更换为三方字体,其实更换全部字体相对比更换部分字体来的简单,我们可以使用runtime来解决.
将字体添加到项目中
添加到项目中
将字体拖入系统resource中, 注意选择add to taget选项
add to target
打开Target 的Build Phases --> Copy Bundle Resource 看一下字体是否在这个标签下 如果没有 点击 + 添加一下即可.
Copy Bundle Resource
然后点击 info 选项, 添加一个字段 Fonts provided by application 这是一个数组, 在数组中添加 item 每个item 就是字体的名字.
info.plist
使用字体
注意:添加进的.tff文件可能不是字体真正的名字, 我们需要遍历找到刚刚添加的字体.用一下代码遍历查找, 添加到appDelegate的didFinishLaunchingWithOptions方法中即可.
for(NSString*fontFamilyNamein[UIFontfamilyNames]) {NSLog(@"fontFamilyName:'%@'",fontFamilyName);for(NSString*fontNamein[UIFontfontNamesForFamilyName:fontFamilyName]) {NSLog(@" font:'%@'",fontName); }NSLog(@"*****************************"); }
区域更换字体(更换某个UILabel的字体)
找到字体名字就可以使用这个三方字体了, 可以用[UIFont fontWithName:@"" size:];
更换全部文字的字体
替换 UILabel 的方法
笔者在接到更换字体需求的时候几乎已经快完成项目了,单个UILabel更换显然已经是不太可能了.网上搜索发现可以使用runtime来在运行时更换UILabel的方法.
+load 方法在加载类的时候就被调用, iOS 应用启动的时候,就会加载所有的类,所以就会调用每个类的 +load 方法。
在 +load 方法中 替换UILabel的可能的初始化方法,在新方法里面设置UILabel的字体,这样就更换了所有UILabel的字体.
注意:在重写+load的时候 要先给父类初始化 调用[super load]方法. 然后使用GCD创建一个dispatch_once_t 保证这段代码只执行一次.
系统的初始化方法和自定义的方法 在runtime中都是SEL类型. 创建两个方法.要实现自定的方法设置字体. 例如:
SEL originalSelector =@selector(init);SEL swizzledSelector =@selector(QQInit);
分别get两个实例方法
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
然后我们直接替换两个方法即可
method_exchangeImplementations(originalMethod, swizzledMethod);
自定义方法的实现
- (instancetype)QQInit {id__self= [selfQQInit];UIFont* font = [UIFontfontWithName:@"FZSEK--GBK1-0"size:self.font.pointSize];if(font) {self.font=font; }return__self;}
替换 UIFont 的方法
上面完成之后我们会发现有一部分的字体没有被替换, 可能是因为我们在UILabel初始化之后又调用了一下几个方法 这几个方法中有设置systemFont的作用.所以又被设置为系统的苹方字了,所以我们还要使用runtime来替换UIFont的这几个方法.
+ (UIFont *)systemFontOfSize:(CGFloat)fontSize;
+ (UIFont *)boldSystemFontOfSize:(CGFloat)fontSize;
+ (UIFont *)italicSystemFontOfSize:(CGFloat)fontSize;
替换方法是一样的,只不过这几个方法是类方法, 所以在getMethod的时候就不能使用class_getInstanceMethod而要使用class_getClassMethod
自定义方法的实现
+(UIFont*)QQsystemFontOfSize:(CGFloat)fontSize {UIFont* font = [UIFontfontWithName:@"FZSEK--GBK1-0"size:fontSize];if(!font) {return[selfQQsystemFontOfSize:fontSize]; }returnfont;}
Test
UILabel*lab = [[UILabelalloc] initWithFrame:self.view.bounds];lab.text =@"按时到合肥拉萨交电话费拉还是快递费卢卡斯 阿萨德会尽快了粉红色的拉客户放假啦是肯定会发生良好的会计法哈收了的看法和沙拉肯定会发了卡萨丁";lab.font = [UIFontsystemFontOfSize:19];lab.numberOfLines =0;[self.view addSubview:lab];
上面的代码设置了文字,也是设置了系统文字的大小,但是并不妨碍我们更换字体.
效果
参考文章-->地址
GitHub-->Demo地址