美文网首页
iOS字体设置,调用方式不变

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

作者: 也嘉 | 来源:发表于2019-12-25 11:14 被阅读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相关图片

    相关文章

      网友评论

          本文标题:iOS字体设置,调用方式不变

          本文链接:https://www.haomeiwen.com/subject/hooqoctx.html