zoukankan      html  css  js  c++  java
  • runtime 使用总结

    - (void)viewDidLoad {
        [super viewDidLoad];
        self.view.backgroundColor = [UIColor grayColor];
    
        for(NSString *familyName in [UIFont familyNames]){
            NSLog(@"Font FamilyName = %@",familyName); //输出字体族科名字
    
            for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
                NSLog(@"------	%@",fontName);         //输出字体族科下字样名字
            }
        }
        
        _myLabel.font = [UIFont fontWithName:@"Copperplate-Bold" size:17.0f];
        _myButton.titleLabel.font = [UIFont fontWithName:@"Heiti SC" size:17.0f];
         
    
        
    }

    //设置系统字体

    苹果默认 Heiti SC  黑体

    +load 总结

    1 当APP程序启动,就会循环调用每个类的+load方法 (不管这个类是否被调用)

    2 直接使用函数内存地址的方式 (*load_method)(cls, SEL_load); 对 +load 方法进行调用的,而不是使用发送消息 objc_msgSend 的方式。

    3 父类(子类)的+load是分开调用的,类(分类)+load方法是分开调用的 (就是说不存在使用子类调用父类+load方法)

    4 优先级 父类+load方法优先于子类+load方法 ; 类+load方法优先于分类的+load方法

    +load 补充:

    1 app项目安装到手机是 以二进制(Match-o)的形式 存储在硬盘中

    2 当点击app图标启动的一刻,将硬盘的二进制 加载进内存,这个过程叫做装载

    3 此时在二进制存放进内存,cpu会等等待load先调用,load 调用时候,对象还没有创建

    +initialize 总结

    1 调用时间: 当父类,子类 接受到第一条消息(类方法/对象方法)之前调用,且仅仅调用一次.

    2 实现机制:属于懒加载,没用到不调用  objc_msgSend 的发消息。

    3 和+load不同  当前类被调用时候,调用+initialize,会触发父类的+initialize 调用(就是调用两遍当前类/父类各一次,优先级,先调用父类,然后子类)

    4 分类实现+initialize 会覆盖本类额+initialize方法 只调用一次.

    总结

     +load+initialize
    调用时机 被添加到 runtime 时 到第一条消息前,可能永远不调用
    同一个类,调用次数
    (不考虑主动调用)
    1次 1次
    调用顺序 父类->本类->分类 父类->本类(如果有分类,则调用分类)
    若自身未实现,是否沿用父类的方法?
    类别中的定义 全都执行,但后于本类的方法 覆盖本类的方法,只执行一个
    线程安全 安全 安全


    正题: runtime 修改系统字体
     
    其实要达成这个目的还可以为UIFont建立一个category,重写systemFontOfSize:,覆盖它的原有方法实现,但是这样做就无法调用系统原有的方法,而且苹果也不建议在category中重写方法:

    利用runtime另写一个方法来和systemFontOfSize:交换

    • Method Swizzling

    主要通过以下面的方法来交换
    method_exchangeImplementations(originalMethod, swizzledMethod);

    这尼玛就是下钩子

    sel(方法编号)----imp(方法实现) 一一对应的关系

    注意 sel--imp 非指针指向地址,imp才是指向函数(方法实现函数)的指针

    imp通过指针找到实现地址,找到二进制代码块

    交换 sel和imp的对应关系

    +  (void)load{
     //只执行一次这个方法
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class class = [self class];
            SEL originalSelector = @selector(systemFontOfSize:);
            SEL swizzledSelector = @selector(mysystemFontOfSize:);
            // Class class = class_getInstanceMethod((id)self);
            Method originalMethod = class_getClassMethod(class, originalSelector);
            Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
            BOOL didAddMethod = class_addMethod(class,originalSelector,
                                                method_getImplementation(swizzledMethod),
                                                method_getTypeEncoding(swizzledMethod));
            if (didAddMethod)
            {
                class_replaceMethod(class,swizzledSelector,
                                    method_getImplementation(originalMethod),
                                    method_getTypeEncoding(originalMethod));
                
            }
            else
            {
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        });
    }
    
    

    相关地址: 

    https://www.jianshu.com/p/4bf2b22b9986

    https://www.jianshu.com/p/8836dfac7f2c

  • 相关阅读:
    提取数据用strpos函数比较,预期和实际不符问题解决
    thinkphp模板中foreach循环没数据的错误解决
    错误之thinkphp模型使用发生的错误
    ThinkPHP添加模板时,犯的三个错
    mysql中的comment用法
    在cmd下输入/g无效
    Windows下PHPUnit安装
    python中string.casefold和string.lower区别
    python3数据类型
    python终端颜色设置
  • 原文地址:https://www.cnblogs.com/ly1973/p/9009578.html
Copyright © 2011-2022 走看看