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(@"------\t%@",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

 

posted @ 2018-05-08 17:27  看谷秀  阅读(238)  评论(0编辑  收藏  举报