OC 中 load 和 initialize 的区别

OC 中 load 和 initialize 的区别

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中文件出现顺序的最后一个
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值