iOS中利用 runtime 一键改变字体

1、准备

我们新建一个项目名叫ChangeFont,然后我就随便找了个名叫loveway.ttf的字体库拖进去,里面的工程目录大概就是这样的

571495-91a43c0fac5f91e4.jpg

目录

现在我们就简单的直接在storyboard上拖了一个label一个button,约束好,像这样

571495-d567ca72aadb692b.jpg

storyboard

嗯,就这样,很简单,运行

571495-e81ac83f048a9545.jpg

运行结果

好的显示正常,没什么问题,接下来改变字体。

2、改变字体

我们之前已经把loveway.ttf这个文件拖进去了,现在在plist文件里面配置一下。打开plist然后加入名为Fonts provided by application的一行,在item里把我们的字体名字加进去

571495-f3a34a72dd21beaa.jpg

plist

最后我们需要保证我们确确实实是加进来了

571495-89647ae861ac1ba8.jpg

phases

这个时候也许你已经迫不及待了,赶紧改字体,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
//  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
- (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];
}

运行一看控制台

571495-0aa0ce498e8e115f.jpg

输出的字体名称部分截图

这什么鬼,我哪知道我刚加进去的字体名称是什么,这咋找

于是想出来个办法,再建一个工程,不加入loveway.ttf这个字体,打印出来,一个个对比,多的那个不就是了吗!bingo,于是花了一会功夫终于找出来了,是FZLBJW--GB1-0,不管了,先试试看行不行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
![](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];
}

运行,结果如下

571495-c438612edb9e919e.png

改变字体后的运行结果

OK!达到效果了,虽然有点挫,但是效果达到了,还不错。

到这里,基本的改变字体效果已达到。

3、查找字体的一种简单的方法

在上面我们可以看到,通过对比的方法找到了FZLBJW--GB1-0这个名字,这里,有一种简单的方法,我们在 Finder 里面找到这个ttf,双击打开(在Xcode里面双击打开没效果),这时候系统就会用苹果自带的字体册打开,如下:

571495-6f429dd17e7f8a8e.jpg

使用字体册打开.rtf

这样我们就可以看到了这个字体的族科名字,我们看到的是FZLiBian-S02S,于是我们在刚才输出全部字体名的控制台搜索一下这个族科名,就可以知道具体的字体名了

571495-71dbd7f8d809bef6.jpg

搜索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
//
//  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
//
//  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

运行

571495-c438612edb9e919e (1).png

我们可以看到字体改变了。

如果有人说我有的想改变字体有的不想改变字体怎么办,我这里有个简单的办法就是设置tag,比如我设置label的tag为10086(随便起的),就让他字体不改变

1462338192307160.png

运行结果

571495-67c22bdfcd9f68b9.png

注意:

1、如果你是代码写控件,你不想改变字体,你只需在创建的时候设置tag为10086

2、上面代码中注释了一行

1
2
3
//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拉进你的工程即可。

需要下载更多字体的可以在字体库下载,所有的代码都可以在这里下载。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,iOS SDK的一键登录功能可以通过第三方库实现。可以使用苹果提供的Apple登录功能进行一键登录。具体步骤如下: 1. 引用提到了几种登录方式,其包括了Apple登录。这意味着你的App已经适配了Apple登录功能。 2. 引用的代码片段展示了微信登录和Apple登录的逻辑。针对Apple登录,你可以使用相应的第三方库来实现一键登录功能。 3. 首先,你需要在苹果开发者平台注册你的App,并获取到相应的App ID。 4. 在你的代码使用该第三方库,并调用相应的方法来初始化Apple登录功能,传入你的App ID。 5. 需要判断用户设备是否安装了微信和是否已登录微信账号,以提供相应的登录选项。 6. 对于Apple登录,你可以调用相应的方法进行授权登录,并指定所需的权限范围。 综上所述,你可以使用适配了Apple登录功能的第三方库来实现iOS SDK的一键登录功能。123 #### 引用[.reference_title] - *1* *2* *3* [flutter在IOS上的登录实现——QQ登录、微信登录、自动识别手机号一键登录、apple登录](https://blog.csdn.net/qq_41510985/article/details/121272687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值