iOS使用runtime设置字体格式

       今天在cocoachina上看了一篇文章,是关于自定义字体格式样式的,自己就学习了一下,然后在这里和大家进行分享。

要自定义字体样式,我们必须要获取ttf格式的字体样式,这里有一个国外的网站,里边字体格式挺多的,大家可以收藏一下:http://www.webpagepublicity.com/free-fonts-b2.html#Free%20Fonts,demo已经上传至github,地址是:https://github.com/IT-iOS-xie/-。废话不多说,下面进行具体介绍。

       首先,我下载了三个字体样式,分别是Americana Dreams Upright.ttf,Bauer Bodoni BT.ttf,loveway.ttf三个不同样式的字体。

       新建工程,将三种字体拖入项目中,然后在info.plist文件中配置字体

       可在target里查看字体是否添加成功。

        接着,在storyboard中拖入控件,并与控制器关联,然后设置控件的属性,如下:

 _label.font = [UIFont fontWithName:@"Americana Dreams Upright" size:17.0f];
    
  _button.titleLabel.font = [UIFont fontWithName:@"Americana Dreams Upright.ttf" size:17.0f];

      运行工程,此时我们可以看到,label中的英文字体设置成功,但是汉字并没有效果,说明一些字体库并不兼容汉字,这个我们可以通过字体侧查看。button的字体设置失败,我们可以知道这种方式并不能有效的设置字体样式。

     我们同样的方法设置其他两种字体,得到的结果是:汉字和英文设置均失败。为什么会这样呢,这里普及一下:在设置字体样式的时候,我们不能直接使用字体族科名字,而需要使用字体族科下字样名字。

      通过mac自带的字体册打开loveway.tff,我们可以看到,它的字体样式为FZLiBian-S02S。

      我们也可以通过遍历族科,获取字体样式。接着设置空间属性。

for (NSString * familyName in [UIFont familyNames]) {
//        字体族科
        NSLog(@"familyName = %@",familyName);
        for (NSString * fontName in [UIFont fontNamesForFamilyName:familyName]) {
//            族科下字体的样式
            NSLog(@"%@",fontName);
        }
    }
    _label.font = [UIFont fontWithName:@"FZLiBian-S02S" size:17.0f];
    
    _button.titleLabel.font = [UIFont fontWithName:@"FZLiBian-S02S" size:17.0f]; 

      运行,我们就可以看到设置成功。 

      字体设置成功,接下来试着封装一下这个方法,需要的时候方便调用。

1.自定义label类MYLabel,继承自UILabel;调用runtime,并在+ (void)load里实现class_addMethod、class_replaceMethod、method_exchangeImplementations一系列方法,

+ (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 ([UIFont fontNamesForFamilyName:CustomFontName]){
                self.font  = [UIFont fontWithName:CustomFontName size:self.font.pointSize];
        }

}

       然后在控制器里,添加label,设置属性,代码如下:

_label2 = [[MYLabel alloc]initWithFrame:CGRectMake(170,350,100, 30)];
    
    _label2.text=@"llklkjkhjkhhu";
    
    _label2.textColor = [UIColor redColor];
    
    _label2.backgroundColor = [UIColor lightGrayColor];
    
    [self.view addSubview:self.label2];

        运行程序,可以看到,字体设置成功。如果我们需要自定义字体,可以直接拖入自定义的label类,配置即可。

       我们也可以通过类扩展的方法实现自定义字体的功能,具体代码如下:

+ (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) {
        
        if (self.tag == 10000) {
            self.font = [UIFont systemFontOfSize:self.font.pointSize];
        } else {
            if ([UIFont fontNamesForFamilyName:CustomFontName])
                self.font  = [UIFont fontWithName:CustomFontName size:self.font.pointSize];
        }
    }

}

      这种方法跟第一种自定义类相比的优点在于可以用于设置按钮等其他空间的字体,缺点是当使用系统字体的时候必须手动设置tag值,耦合性略强。

希望有大神可以帮忙进行改进。

原文地址:https://www.cnblogs.com/xiejw/p/5462896.html