美文网首页
(三)+initialize方法

(三)+initialize方法

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

+initialize方法

面试题:
1.+initilize方法什么时候调用?
析:+initialize方法会在【类】第一次接收到消息的时候调用
2.+initilize方法调用顺序?
析:a.先调用父类的+initilize方法,再调用子类的+initilize方法
     (先初始化父类,再初始化子类,每个类只会初始化一次)
3.+initilize和+load方法的区别?
析:+initilize方法是通过消息转发机制(objc_msgSend)去实现的
   而+load方法,系统调用的时候是根据方法的地址去调用的

4.+initilize方法的特点?
析:如果子类没有实现+initilize方法,会调用父类的+initilize(所以父类的initilize可能会被调用多次)
   如果分类实现了+initilize方法,则会覆盖类本身的+initilize方法
   
5.+initilize底层原理?
析:见下分析

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

下面我们逐个分析

1.+initialize方法会在【类】第一次接收到消息的时候调用
Animal.h
#import <Foundation/Foundation.h>
@interface Animal : NSObject
@end

Animal.m
#import "Animal.h"
@implementation Animal
+(void)initialize{
    NSLog(@"Animal--initialize");
}
@end

main.m
#import <Foundation/Foundation.h>
#import "Animal.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
       [Animal alloc]; //+initialize方法会在【类】第一次接收到消息的时候调用
    }
    return 0;
}
打印:Animal--initialize

-----------
2.+initilize方法调用顺序
Animal.h
#import <Foundation/Foundation.h>
@interface Animal : NSObject
@end

Animal.m
#import "Animal.h"
@implementation Animal
+(void)initialize{
    NSLog(@"Animal--initialize");
}
@end

Person.h
#import "Animal.h"
@interface Person : Animal
@end

Person.m
#import "Person.h"
@implementation Person
+(void)initialize{
    NSLog(@"Person--initialize");
}
@end

main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {  
        [Person alloc];  
        //先调用父类的+initilize方法,再调用子类的+initilize方法
        //先初始化父类,再初始化子类,每个类只会初始化一次
    }
    return 0;
}
打印:Animal--initialize
     Person--initialize
---------------
 
3.如果子类没有实现+initilize方法,会调用父类的+initilize(父类的initilize可能会被调用多次)
  会被调用多次原因:子类米有实现initialize的方法(通过superclass_isa调用的),但这并不代表父类初始化了多次
Animal.h
#import <Foundation/Foundation.h>
@interface Animal : NSObject
@end

Animal.m
#import "Animal.h"
@implementation Animal
+(void)initialize{
    NSLog(@"Animal--initialize");
}
@end

Person.h
#import "Animal.h"
@interface Person : Animal
@end

Person.m
#import "Person.h"
@implementation Person
@end

main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {  
        [Person alloc];  
    }
    return 0;
}
打印:Animal--initialize
     Animal--initialize
-----------------

4.分类实现了+initilize方法,则会覆盖类本身的+initilize方法
Animal.h
#import <Foundation/Foundation.h>
@interface Animal : NSObject
@end

Animal.m
#import "Animal.h"
@implementation Animal
+(void)initialize{
    NSLog(@"Animal--initialize");
}
@end

Person.h
#import "Animal.h"
@interface Person : Animal
@end

Person.m
#import "Person.h"
@implementation Person
+(void)initialize{
    NSLog(@"Person--initialize");
}
@end

Person+myPerson.h
#import "Person.h"
@interface Person (myPerson)
@end

Person+myPerson.m
#import "Person+myPerson.h"
@implementation Person (myPerson)
+(void)initialize{
    NSLog(@"Person(myPerson)--initialize");
}
@end

main.m
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {  
        [Person alloc];  
    }
    return 0;
}
打印:Animal--initialize
     Person(myPerson)--initialize

源码分析

  • 由于objc_msgSend的底层是通过汇编实现的 (这里第一步可详看objc-msg-arm64.s 里面的objc_msgSend)

  • 我们在editScheme->run->Arguments->OBJC_PRINT_INITIALIZE_METHODS:YES

    • 我们发现:在后台打印了

      objc[93254]: INITIALIZE: thread 0x1000be5c0: calling +[Animal initialize]
      2019-03-10 22:45:45.984948+0800 04.initilize方法[93254:6315621] Animal--initialize
      objc[93254]: INITIALIZE: thread 0x1000be5c0: finished +[Animal initialize]
      objc[93254]: INITIALIZE: thread 0x1000be5c0: Animal is fully +initialized
      objc[93254]: INITIALIZE: thread 0x1000be5c0: calling +[Person initialize]
      2019-03-10 22:45:45.985338+0800 04.initilize方法[93254:6315621] Person(myPerson)--initialize
      objc[93254]: INITIALIZE: thread 0x1000be5c0: finished +[Person initialize]
      objc[93254]: INITIALIZE: thread 0x1000be5c0: Person is fully +initialized
      Program ended with exit code: 0
      
    • 由此,我们发现几个关键字:【calling +】、【finished +】、【is fully +initialized】

    • 我们在objc-runtime-new.mm里面发现

initialize_01.jpeg
局部分析:
void _class_initialize(Class cls)
{
    assert(!cls->isMetaClass());
    Class supercls;
    bool reallyInitialize = NO;

    //先调用父类的+initilize方法,再调用子类的+initilize方法
    //(先初始化父类,再初始化子类,每个类只会初始化一次)
    //如果子类没有实现+initilize方法,会调用父类的+initilize(所以父类的initilize可能会被调用多次)
    supercls = cls->superclass;
    if (supercls  &&  !supercls->isInitialized()) {
        _class_initialize(supercls);
    }
    。。。    
}

友情链接:

相关文章

网友评论

      本文标题:(三)+initialize方法

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