iOS

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

2019-03-12  本文已影响31人  dandelionYD

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

分析:


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

友情链接:

上一篇 下一篇

猜你喜欢

热点阅读