美文网首页
iOS initialize 和load

iOS initialize 和load

作者: 霸_霸霸 | 来源:发表于2018-08-20 10:09 被阅读9次

    记录一下initializeload方法的调用时机

    问题一 loadinitialize哪个更早执行?

    1. main函数

    #import <UIKit/UIKit.h>
    #import "AppDelegate.h"
    
    int main(int argc, char * argv[]) {
        @autoreleasepool {
            
            NSLog(@"%s",__FUNCTION__);
            
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }
    

    2. 继承自NSObject的Person类

    #import "Person.h"
    
    @implementation Person
    
    + (void)load {
        NSLog(@"%s",__FUNCTION__);
    }
    
    + (void)initialize {
        [super initialize];
        NSLog(@"%s %@",__FUNCTION__, [self class]);
    }
    
    - (instancetype)init {
        self = [super init];
        if (self) {
            NSLog(@"%s",__FUNCTION__);
        }
        return self;
    }
    
    @end
    

    运行--结果


    结果1

    只执行了load, 未调用initialize, 猜测是因为未实例化Person对象

    3. 实例化Person对象

    在ViewController中为Person创建一个实例对象

    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        Person *p1 = [Person new];
    }
    

    运行--结果


    结果2

    可以看到, 先调用load, 然后调用main, 由于实例化了一个Person对象, 所以调用了initialize方法, 最后是init方法

    结论2: load早于main早于initialize早于init

    还有一些大神总结的区别

    load

    1. 对于加入运行期系统的类及分类,必定会调用此方法,且仅调用一次。

    2. iOS会在应用程序启动的时候调用load方法,在main函数之前调用

    3. 执行子类的load方法前,会先执行所有超类的load方法,顺序为父类->子类->分类

    4. 在load方法中使用其他类是不安全的,因为会调用其他类的load方法,而如果关系复杂的话,就无法判断出各个类的载入顺序,类只有初始化完成后,类实例才能进行正常使用

    5. load 方法不遵从继承规则,如果类本身没有实现load方法,那么系统就不会调用,不管父类有没有实现(跟下文的initialize有明显区别)

    6. 尽可能的精简load方法,因为整个应用程序在执行load方法时会阻塞,即,程序会阻塞直到所有类的load方法执行完毕,才会继续

    7. load 方法中最常用的就是方法交换method swizzling

    initialize

    1. 在首次使用该类之前由运行期系统(非人为)调用,且仅调用一次

    2. 惰性调用,只有当程序使用相关类时,才会调用

    3. 运行期系统会确保initialize方法是在线程安全的环境中执行,即,只有执行initialize的那个线程可以操作类或类实例。其他线程都要先阻塞,等待initialize执行完

    4. 如果类未实现initialize方法,而其超类实现了,那么会运行超类的实现代码,而且会运行两次(load 第5点)

      (1) initialize 遵循继承规则
      (2) 初始化子类的的时候会先初始化父类,然后会调用父类的initialize方法,而子类没有覆写initialize方法,因此会再次调用父类的实现方法
      (3) 鉴于此,initialize方法实现如下:

       + (void)initialize {
          if (self == [People class]) {
              NSLog(@"%@ initialize", self);
          }
      }
    
    1. initialize方法也需要尽量精简,一般只应该用来设置内部数据,比如,某个全局状态无法在编译期初始化,可以放在initialize里面。
    static NSMutableArray *kSomeObjects;
     @implementation People
     + (void)initialize {
         if (self == [People class]) {
             kSomeObjects = [NSMutableArray new]; 
         }
     }
    

    相关文章

      网友评论

          本文标题:iOS initialize 和load

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