美文网首页iOS
(二)load方法(原理+调用顺序)

(二)load方法(原理+调用顺序)

作者: dandelionYD | 来源:发表于2019-03-12 16:47 被阅读31次

    load方法(原理+调用顺序)

    面试题:

    1.load它的调用顺序?
    析:load方法会在runtime加载【类】、【分类】的时候调用
        每个【类】、【分类】的+load,在程序运行过程中只调用一次
        
       调用顺序:
            a.先调用类的+load方法
                (1)按照编译先后的顺序调用(先编译、先调用)
                (2)调用子类的+load之前会先调用父类的+load方法
            b.再调用分类的+load方法
                 (1).按照编译先后的顺序调用(先编译、先调用)
    2.系统的load的原理?
    析:见下详解 
    

    准备:首先搭建好可以跑runtime源码的过程,参考配置运行objc4-750和使用

    gitHub_Demo

    下面我们来看看代码执行:

    Animal.h
    #import <Foundation/Foundation.h>
    @interface Animal : NSObject
    @end
    
    Animal.m
    #import "Animal.h"
    @implementation Animal
    + (void)load{
        NSLog(@"Animal");
    }
    @end
    ------------------------
    Animal2.h
    #import <Foundation/Foundation.h>
    @interface Animal2 : NSObject
    @end
    
    Animal2.m
    #import "Animal2.h"
    @implementation Animal2
    + (void)load{
        NSLog(@"Animal2");
    }
    @end
    ------------------------
    Person.h
    #import "Animal.h"
    @interface Person : Animal
    @end
    
    Person.m
    #import "Person.h"
    @implementation Person
    + (void)load{
        NSLog(@"Person");
    }
    @end
    -----------------------
    Student.h
    #import "Person.h"
    @interface Student : Person
    @end
    
    Student.m
    #import "Student.h"
    @implementation Student
    + (void)load{
        NSLog(@"Student");
    }
    @end
    ------------------------
    Animal+myAnimal.h
    #import "Animal.h"
    @interface Animal (myAnimal)
    @end
    
    Animal+myAnimal.m
    #import "Animal+myAnimal.h"
    @implementation Animal (myAnimal)
    + (void)load{
        NSLog(@"分类--Animal");
    }
    @end
    ------------------------
    Person+myPerson.h
    #import "Person.h"
    @interface Person (myPerson)
    @end
    
    Person+myPerson.m
    #import "Person+myPerson.h"
    @implementation Person (myPerson)
    + (void)load{
        NSLog(@"分类--Person");
    }
    @end
    ------------------------
    Student+myStudent.h
    #import "Student.h"
    @interface Student (myStudent)
    @end
    
    Student+myStudent.m
    #import "Student+myStudent.h"
    @implementation Student (myStudent)
    + (void)load{
        NSLog(@"分类--Student");
    }
    @end
    ------------------------
    

    运行结果 :

    load_01.png

    分析:

    • 根据加载的类的顺序:
      • 先执行了Animal2类
      • 再执行了Animal类
      • 再执行了Animal的子类Peson类
      • 再执行了Person的子类Student类
    • 等所有的类加载完了,就按照加载的顺序执行分类(先编译,先调用原则)
      • 分类Peson+myPerson
      • 分类Student+myStudent
      • 分类Animal+myAnimal

    OR:

    在:Edit Scheme.. -> Run_debug. -> Arguments -> Environment variables 中添加 :OBJC_PRINT_LOAD_METHODS为YES (为什么这么设置?:我们通过下面分析源码,发现add_class_to_loadable_list方法里面有打印的设置【PrintLoading】)

    见后台部分打印:

    objc[91622]: LOAD: class 'Animal2' scheduled for +load
    objc[91622]: LOAD: class 'Animal' scheduled for +load
    objc[91622]: LOAD: class 'Person' scheduled for +load
    objc[91622]: LOAD: class 'Student' scheduled for +load
    objc[91622]: LOAD: category 'Person(myPerson)' scheduled for +load
    objc[91622]: LOAD: category 'Student(myStudent)' scheduled for +load
    objc[91622]: LOAD: category 'Animal(myAnimal)' scheduled for +load
    objc[91622]: LOAD: +[Animal2 load]
    

    原理:

    1.首先 我们打个 断点—>如下


    load_02.png

    我们看左边:发现执行了load_images方法,点击进去

    我们通过找到load_images,然后根据上下文打断点

    load_03.png load_04.png
    补充:
    1.分类的test方法(类方法和实例方法),是通过 objc_mesgSend的方法的(isa)来执行方法的
    2.一般系统自动调用的load方法不一样哟,但是[Student load]; 手动调用的时候是通过消息发送机制的 先调用分类的(如果分类没写),再调用本类的(如果本类没写),会自动调用父类的load方法
    

    分析

    Student+myStudent.h
    #import "Student.h"
    @interface Student (myStudent)
    +(void)play;
    -(void)walk;
    @end
    
    Student+myStudent.m
    #import "Student+myStudent.h"
    @implementation Student (myStudent)
    + (void)load{
        NSLog(@"分类--Student");
    }
    +(void)play{
        NSLog(@"Student的分类的类方法play");
    }
    -(void)walk{
        NSLog(@"Student的分类的实例方法walk");
    }
    @end
    ---------------
    
    main.m
    #import <Foundation/Foundation.h>
    #import "Student+myStudent.h"
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            [Student play]; //打个断点
            NSLog(@"-------------");
            
            Student *stu = [Student new];
            [stu walk];
            NSLog(@"-------------");
            
            [Student load];  //打个断点
        }
        return 0;
    }
    
    load_05.png load_06.png

    友情链接:

    相关文章

      网友评论

        本文标题:(二)load方法(原理+调用顺序)

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