iOS字体设置,调用方式不变

2019-12-25  本文已影响0人  也嘉

iOS设置字体有两种方式

  1. 是导入我们的字体到工程,调用[UIFont fontWithName:fontName size:size]使用我们的自定义字体;
  2. 是替换系统设置字体的方法systemFontOfSize、boldSystemFontOfSize等,调用方式就不变。
    第二种方式比较灵活,更换字体改动较少。

本文就说说第二种方式。

一、新建UIFont的扩展

@interface UIFont (UIFont_Extension)


@end

@implementation UIFont (UIFont_Extension)

+ (void)setFontName:(NSString *)fontName {

    objc_setAssociatedObject(self, @"fontName_", fontName, OBJC_ASSOCIATION_COPY);
}

+ (NSString *)fontName {

    return objc_getAssociatedObject(self, @"fontName_");
}

+ (UIFont *) replacement_systemFontOfSize:(CGFloat)fontSize {
    
    return [UIFont fontWithName:self.fontName size:fontSize];
}

+ (UIFont *) replacement_boldSystemFontOfSize:(CGFloat)fontSize {
    
    return [UIFont fontWithName:self.fontName size:fontSize];
}

+ (UIFont *) replacement_italicSystemFontOfSize:(CGFloat)fontSize {
    
    return [UIFont fontWithName:self.fontName size:fontSize];
}

@end

二、新建替换字体的类UIFontExchange

1). 交换系统定义方法与自定义方法的实现

- (void) replacement_systemFont {
    
    //交换systemFontOfSize方法
    Method systemFontOfSize_ = class_getClassMethod([UIFont class], @selector(systemFontOfSize:));
    Method replacementSystemFontOfSize_ = class_getClassMethod([UIFont class], @selector(replacement_systemFontOfSize:));
    if (systemFontOfSize_ && replacementSystemFontOfSize_
        && strcmp(method_getTypeEncoding(systemFontOfSize_), method_getTypeEncoding(replacementSystemFontOfSize_)) == 0)
        method_exchangeImplementations(systemFontOfSize_, replacementSystemFontOfSize_);
    
    //交换boldSystemFontOfSize方法
    Method boldSystemFontOfSize_ = class_getClassMethod([UIFont class], @selector(boldSystemFontOfSize:));
    Method replacementBoldSystemFontOfSize_ = class_getClassMethod([UIFont class], @selector(replacement_boldSystemFontOfSize:));
    if (boldSystemFontOfSize_ && replacementBoldSystemFontOfSize_
        && strcmp(method_getTypeEncoding(boldSystemFontOfSize_), method_getTypeEncoding(replacementBoldSystemFontOfSize_)) == 0)
        method_exchangeImplementations(boldSystemFontOfSize_, replacementBoldSystemFontOfSize_);
    
    //交换italicSystemFontOfSize方法
    Method italicSystemFontOfSize_ = class_getClassMethod([UIFont class], @selector(italicSystemFontOfSize:));
    Method replacementItalicSystemFontOfSize_ = class_getClassMethod([UIFont class], @selector(replacement_italicSystemFontOfSize:));
    if (italicSystemFontOfSize_ && replacementItalicSystemFontOfSize_
        && strcmp(method_getTypeEncoding(italicSystemFontOfSize_), method_getTypeEncoding(replacementItalicSystemFontOfSize_)) == 0)
        method_exchangeImplementations(italicSystemFontOfSize_, replacementItalicSystemFontOfSize_);
}
解析
  1. class_getClassMethod得到类的类方法,得到UIFont的类方法systemFontOfSize,和UIFont扩展中的类方法replacement_systemFontOfSize。
  2. method_getTypeEncoding得到systemFontOfSize方法的参数和返回值组成的字符串
    NSLog(@"%s", method_getTypeEncoding(systemFontOfSize_));
    控制台输出:@24@0:8d16
    看着方法声明解释
    +(UIFont *)systemFontOfSize:(CGFloat)fontSize;
    • @ 表示返回一个objective-c的对象
    • 24 表示整个方法参数占位的总长度(24bytes)
    • @0 在offset为0的地方有一个objective-c的对象,在objective-c method里,首个对象是自身self
    • :8 在offset为8的地方有一个SEL
    • d16 在offset 16的地方有一个double类型的参数
  3. strcmp C库函数int strcmp(const char *str1, const char *str2),字符串比较,返回0则这两个地址指向的字符串是一样的。
  4. method_exchangeImplementations 交换两个方法的实现,也就是交换IMP指针

三、根据字体文件路径获取字体

对于TTF、OTF的字体都有效,但是对于TTC字体,只取出了一种字体。

- (UIFont *)fontWithPath:(NSString*)path size:(CGFloat)size {
    
    NSURL *fontUrl = [NSURL fileURLWithPath:path];
    CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL((__bridge CFURLRef)fontUrl);
    CGFontRef fontRef = CGFontCreateWithDataProvider(fontDataProvider);
    CGDataProviderRelease(fontDataProvider);
    CTFontManagerRegisterGraphicsFont(fontRef, NULL);
    NSString *fontName = CFBridgingRelease(CGFontCopyPostScriptName(fontRef));
    UIFont *font = [UIFont fontWithName:fontName size:size];
    CGFontRelease(fontRef);
    
    return font;
}

设置字体

- (void) setFontName:(NSString *)fontName {
    
    NSString *filePath = [[NSBundle mainBundle] pathForResource:fontName ofType:nil];
    if([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
        NSString *fontStr = [self fontWithPath:filePath size:14.0].fontName;
        [UIFont setFontName:fontStr];
        [NSUserDefaults setSettingValue:fontName type:SettingTypeFontFamily];
    }
    else {
        //默认设置的是苹方
        [UIFont setFontName:@"PingFangSC-Regular"];
    }
}

我做的是在UIFontExchange类的load方法里初始化一个实例调用交换方法和[self setFontName:YourfontName]的。

最后附上我找到的method_getTypeEncoding返回值解析相关的图
method_getTypeEncoding相关图片
上一篇下一篇

猜你喜欢

热点阅读