美文网首页
OC 中 load 和 initialize 的区别

OC 中 load 和 initialize 的区别

作者: 赵邦华 | 来源:发表于2020-10-29 23:08 被阅读0次

    load:

    • +load是一个类方法,当程序载入时,在main函数执行之前,带有+load方法类(Class)或者种类(Category)就会执行+load方法(每个+load方法只执行一次),比如:

      @interface Person : NSObject
      @end
        
      @implementation Person
      +(void)load {
          NSLog(@"Person is loaded");
      }
      @end
        
      int main(int argc, const char *argv[])
      {
          @autoreleasepool {
              // insert code here...
              NSLog(@"main is executed");
          }
          return 0;
      }
      // Person is loaded
      // main is executed
      

      我们可以看到,Person类中的+load方法在main执行前就被调用了

    • 当父类和子类都实现+load方法时,父类和子类的+load方法都会执行(都只执行一次),且父类的+load方法执行顺序要优先于子类,比如:

      @interface Person : NSObject
      @end
      
      @interface Father : Person
      @end
        
      @implementation Person
      +(void)load {
          NSLog(@"Person is loaded");
      }
      @end
      
      @implementation Father
      +(void)load {
          NSLog(@"Father is loaded");
      }
      @end
        
      //  Person is loaded
      //  Father is loaded
      

      我们可以看到FahterPerson的子类,Person执行+load方法后Father才执行+load方法

    • 当子类未实现+load方法时,不会调用父类+load方法,比如:

      @implementation Person
      +(void)load {
          NSLog(@"Person is loaded");
      }
      @end
      
      @implementation Father
      //+(void)load {
      //    NSLog(@"Father is loaded");
      //}
      @end
      
      //  Person is loaded
      
    • 当子类实现+load方法,而父类没有实现+load方法时,只调用子类的+load方法:

      @implementation Person
      //+(void)load {
      //    NSLog(@"Person is loaded");
      //}
      @end
      
      @implementation Father
      +(void)load {
          NSLog(@"Father is loaded");
      }
      @end
        
      //  Father is loaded
      
    • 类中的+load方法执行顺序要优先于种类(Category),种类中+load方法的执行顺序和Compile Sources中出现的顺序一致:

      @implementation Person
      +(void)load {
          NSLog(@"Person is loaded");
      }
      @end
      
      @implementation Person (Category1)
      +(void)load {
          NSLog(@"Person Category1 is loaded");
      }
      @end
      
      @implementation Person (Category2)
      +(void)load {
          NSLog(@"Person Category2 is loaded");
      }
      @end
        
      @implementation Person (Category3)
      +(void)load {
          NSLog(@"Person Category3 is loaded");
      }
      @end
        
      // Person is loaded
      // Person Category3 is loaded
      // Person Category1 is loaded
      // Person Category2 is loaded
      

      可以看到Person类的+load先于所有种类的执行顺序,而Compile Sources中Person种类出现的顺序是3,1,2,这对应+load执行的顺序

    • 当有多个不同的类的时候,每个类+load 执行顺序与其在Compile Sources出现的顺序一致

    • +load是线程安全的,要避免在+load内堵塞线程。

    initialize

    • 在类收到第一条消息的时候调用,在main函数开始执行后(因为类方法的调用在main中),可能某个类会一直不执行+initialize,因为这个类可能只是被加载到程序中,而没有被调用(收到消息),每个类只执行+initialize一次。

    • 父类的+initialize方法会比子类先执行:

      @implementation Person
      +(void)initialize {
          NSLog(@"Person is initialized");
      }
      @end
      
      @implementation Father
      +(void)initialize {
          NSLog(@"Father is initialized");
      }
      @end
        
      int main(int argc, const char *argv[])
      {
          @autoreleasepool {
              Father *father = [[Father alloc] init];
              Person *person = [[Person alloc] init];
          }
          return 0;
      }
      
      // Person is initialized
      // Father is initialized
      
    • 当子类未实现+initialize方法时,会调用父类+initialize方法(这样使得同一种+initialize可能会被执行多次,但这并不与每个类只执行+initialize一次相矛盾)。

      @implementation Person
      +(void)initialize {
          NSLog(@"Person is initialized");
      }
      @end
      
      @implementation Father
      //+(void)initialize {
      //    NSLog(@"Father is initialized");
      //}
      @end
      
      int main(int argc, const char *argv[])
      {
          @autoreleasepool {
              Father *father = [[Father alloc] init];
          }
          return 0;
      }
      
      //  Person is initialized
      //  Person is initialized
      
    • 当有多个Category都实现了+initialize方法时,会覆盖类中的方法,+initialize方法只执行一次(会执行Compile Sources 列表中最后一个Category 的+initialize方法)

      @implementation Person
      +(void)initialize {
          NSLog(@"Person is initialized");
      }
      @end
        
      @implementation Person (Category1)
      +(void)initialize {
          NSLog(@"Person Category1 is initialized");
      }
      @end
        
      @implementation Person (Category2)
      +(void)initialize {
          NSLog(@"Person Category2 is initialized");
      }
      @end
        
      @implementation Person (Category3)
      +(void)initialize {
          NSLog(@"Person Category3 is initialized");
      }
      @end
        
      // Person Category2 is initialized
      

      Compile Sources中Catergory出现的顺序是3,2,1,+initialize执行一次,执行的是最后一个(1)。

    • +initiallize是线程安全的,要避免在+initiallize内堵塞线程。

    总结

    方法 +load +initialize
    执行时间 类载入程序时 类第一次接受消息时
    执行次数 每个+load方法只执行一次,不会出现重复执行 每个类的+initialize方法只执行一次,可能会重复执行
    父类是否优先于子类执行
    子类不实现时,是否调用父类 是(导致父类+initialize方法执行次数+1)
    子类是否覆盖父类
    Category是否覆盖类
    类的执行是否优先于Category 是(因为只执行一次)
    多个Category执行次数 Category的数量 和类一起,总共一次
    多个Category执行顺序 Compile Sources中文件出现的顺序 Compile Sources中文件出现顺序的最后一个

    相关文章

      网友评论

          本文标题:OC 中 load 和 initialize 的区别

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