美文网首页
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的区别

    OC中的load和initialize的区别 调用方式load是根据函数地址直接调用initialize是通过ob...

  • iOS学习回顾

    oc部分 1. load和initialize的区别(利用load方法,MJRefresh在app启动时 在UIT...

  • load、initialize详解及区别

    load、initialize方法的区别? load、initialize的调用顺序? load initialize

  • OC 中load和initialize的区别

    + (void)load;+(void)initialize; load:load方法在这个文件被程序装载时调用。...

  • OC中load 和initialize 的区别

    OC文件在编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会...

  • OC中load和initialize的区别

    OC文件在编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会...

  • OC 中 load 和 initialize 的区别

    load: +load是一个类方法,当程序载入时,在main函数执行之前,带有+load方法类(Class)或者种...

  • OC中load和initialize的区别

    OC文件在编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会...

  • 运行时的应用

    1、load和initialize的区别 +load和+initialize是 Objective-C runti...

  • 技术点

    1、oc中 load 和initialize 方法的异同? 连接 load 方法: 对于每个类(class)及分类...

网友评论

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

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