Objective-C 中 +load 与 +initialize

来源:互联网 发布:长庚医院网络挂号预约 编辑:程序博客网 时间:2024/06/07 06:21

类的加载

java语言里,可以通过如下代码来实现加载类的时候执行对类的操作,一般叫:类初始块,或者,类加载块。比如:

 

Java代码  收藏代码
  1. public class MyClass{    
  2.     static{    
  3.         ……    
  4.     }    
  5. }   

 objc语言里,对应的机制是,2个类初始化方法,+(void)load+(void)initialize

比如:

 

Java代码  收藏代码
  1. #import "Constants.h"    
  2. @implementation Constants    
  3.   
  4. + (void)initialize{    
  5.     NSLog(@"init constants >>>>>>>>>>");    
  6. }    
  7.   
  8. + (void)load{    
  9.     NSLog(@"load constants >>>>>>>>>>");    
  10. }    
  11.   
  12. @end   

 两个方法有一些不同。

load,是加载类的时候,这里是Constants类,就会调用。也就是说,ios应用启动的时候,就会加载所有的类,就会调用这个方法。

 

这样有个缺点,当加载类需要很昂贵的资源,或者比较耗时的时候,可能造成不良的用户体验,或者系统的抖动。这时候,就要考虑initialize方法了。这个方法可看作类加载的延时加载方法。类加载后并不执行该方法。只有当实例化该类的实例的时候,才会在第一个实例加载前执行该方法。比如:

 

 

[Constants alloc];

alloc将为Constants实例在堆上分配变量。这时调用一次initialize方法,而且调用一次,也就是说再次alloc操作的时候,不会再调用initialize方法了。

initialize 会在运行时仅被触发一次,如果没有向类发送消息的话,这个方法将不会被调用。这个方法的调用是线程安全的。父类会比子类先收到此消息

 

如果希望在类及其Categorgy中执行不同的初始化的话可以使用+load

+(void)load; Objective-C运行时载入类或者Category时被调用

这个方法对动态库和静态库中的类或(Category)都有效.

 

Mac OS X 10.5及之后的版本,初始化的顺序如下:

1. 调用所有的Framework中的初始化方法

2. 调用所有的+load方法

3. 调用C++的静态初始化方及C/C++中的__attribute__(constructor)函数

4. 调用所有链接到目标文件的framework中的初始化方法

另外

一个类的+load方法在其父类的+load方法后调用

一个Category+load方法在被其扩展的类的自有+load方法后调用

+load方法中,可以安全地向同一二进制包中的其它无关的类发送消息,但接收消息的类中的+load方法可能尚未被调用。

 

下面是一个load的顺序

 

Java代码  收藏代码
  1. #import <Foundation/Foundation.h>    
  2.   
  3. #define LOAD +(void)load{NSLog(@"%s", __PRETTY_FUNCTION__);}    
  4. #define INITIALIZE +(void)initialize{NSLog(@"%s", __PRETTY_FUNCTION__);}    
  5. #define DEF_CLASS(clsName) @interface clsName : NSObject \    
  6. @end \    
  7. @implementation clsName \    
  8. INITIALIZE \    
  9. LOAD \    
  10. @end    
  11.   
  12. DEF_CLASS(C1)   //1    
  13. DEF_CLASS(C2)   //2    
  14.   
  15. @interface C1 (Hello)    
  16. + (void)hello;    
  17. @end    
  18. @implementation C1 (Hello)    
  19. INITIALIZE       //   
  20. LOAD            //3    
  21. + (void)hello    
  22. {    
  23.     NSLog(@"Hello");    
  24. }    
  25. + (void)hi    
  26. {    
  27.     NSLog(@"hi");    
  28. }    
  29. @end    
  30.   
  31. @interface C2 (Hello)    
  32. @end    
  33. @implementation C2 (Hello)    
  34. + (void)load    //4   
  35. {    
  36.     NSLog(@"%s", __PRETTY_FUNCTION__);    
  37. }    
  38.   
  39. + (void)initialize    //   
  40. {    
  41.     NSLog(@"%s", __PRETTY_FUNCTION__);    
  42. }    
  43. @end    
  44. int main (int argc, const char * argv[])    
  45. {    
  46.       
  47.     @autoreleasepool {    
  48.         // insert code here...    
  49.         //        [[C1 alloc]init]; // 向C1发送消息    
  50.         //       [[C2 alloc]init]; // 向C2发送消息    
  51.     }    
  52.     return 0;    
  53. }    

 输出:

2012-08-14 00:47:07.859 www[654:903] +[C1 load]

2012-08-14 00:47:07.862 www[654:903] +[C2 load]

2012-08-14 00:47:07.863 www[654:903] +[C1(Hello) load]

2012-08-14 00:47:07.863 www[654:903] +[C2(Hello) load]

以上只执行了load方法。

 

 

loadinitialize的顺序:

 

Java代码  收藏代码
  1. #import <Foundation/Foundation.h>    
  2.   
  3. #define LOAD +(void)load{NSLog(@"%s", __PRETTY_FUNCTION__);}    
  4. #define INITIALIZE +(void)initialize{NSLog(@"%s", __PRETTY_FUNCTION__);}    
  5. #define DEF_CLASS(clsName) @interface clsName : NSObject \    
  6. @end \    
  7. @implementation clsName \    
  8. INITIALIZE \    
  9. LOAD \    
  10. @end    
  11.   
  12. DEF_CLASS(C1)   //1    
  13. DEF_CLASS(C2)   //2    
  14.   
  15. @interface C1 (Hello)    
  16. + (void)hello;    
  17. @end    
  18. @implementation C1 (Hello)    
  19. INITIALIZE       //4    
  20. LOAD            //3    
  21. + (void)hello    
  22. {    
  23.     NSLog(@"Hello");    
  24. }    
  25. + (void)hi    
  26. {    
  27.     NSLog(@"hi");    
  28. }    
  29. @end    
  30.   
  31. @interface C2 (Hello)    
  32. @end    
  33. @implementation C2 (Hello)    
  34. + (void)load    //5    
  35. {    
  36.     NSLog(@"%s", __PRETTY_FUNCTION__);//[C1 hello];//NSLog(@"%s", __PRETTY_FUNCTION__);    
  37. }    
  38.   
  39. + (void)initialize    //6    
  40. {    
  41.     NSLog(@"%s", __PRETTY_FUNCTION__);    
  42. }    
  43. @end    
  44. int main (int argc, const char * argv[])    
  45. {    
  46.       
  47.     @autoreleasepool {    
  48.         // insert code here...    
  49.         [[C1 alloc]init]; // 向C1发送消息    
  50.         [[C2 alloc]init]; // 向C2发送消息    
  51.     }    
  52.     return 0;    
  53. }  

 输出:

2012-08-14 00:55:26.769 www[741:903] +[C1 load]

2012-08-14 00:55:26.772 www[741:903] +[C2 load]

2012-08-14 00:55:26.772 www[741:903] +[C1(Hello) load]

2012-08-14 00:55:26.773 www[741:903] +[C2(Hello) load]

2012-08-14 00:55:26.773 www[741:903] +[C1(Hello) initialize]

2012-08-14 00:55:26.774 www[741:903] +[C2(Hello) initialize]

貌似类中的initialize没有执行。alloc]init某个类就调用每个类的initialize方法。

假如只[[C2 alloc]init];就只执行C2类中的initialize方法 ,输出:

 

2012-08-14 00:55:26.769 www[741:903] +[C1 load]

2012-08-14 00:55:26.772 www[741:903] +[C2 load]

2012-08-14 00:55:26.772 www[741:903] +[C1(Hello) load]

2012-08-14 00:55:26.773 www[741:903] +[C2(Hello) load]

2012-08-14 00:55:26.774 www[741:903] +[C2(Hello) initialize]

 

 

 

再看下面代码:

 

Java代码  收藏代码
  1. #import <Foundation/Foundation.h>    
  2.   
  3. #define LOAD +(void)load{NSLog(@"%s", __PRETTY_FUNCTION__);}    
  4. #define INITIALIZE +(void)initialize{NSLog(@"%s", __PRETTY_FUNCTION__);}    
  5. #define DEF_CLASS(clsName) @interface clsName : NSObject \    
  6. @end \    
  7. @implementation clsName \    
  8. INITIALIZE \    
  9. LOAD \    
  10. @end    
  11.   
  12. DEF_CLASS(C1)   //1    
  13. DEF_CLASS(C2)   //2    
  14.   
  15. @interface C1 (Hello)    
  16. + (void)hello;    
  17. @end    
  18. @implementation C1 (Hello)    
  19. INITIALIZE       //4    
  20. LOAD            //3    
  21. + (void)hello    
  22. {    
  23.     NSLog(@"Hello");    
  24. }    
  25. + (void)hi    
  26. {    
  27.     NSLog(@"hi");    
  28. }    
  29. @end    
  30.   
  31. @interface C2 (Hello)    
  32. @end    
  33. @implementation C2 (Hello)    
  34. + (void)load    //5    
  35. {    
  36.     [C1 hello];//NSLog(@"%s", __PRETTY_FUNCTION__); //这里做了修改,调用了C1的静态方法,导致执行了C1的+initialize   
  37. }    
  38.   
  39. + (void)initialize    //6    
  40. {    
  41.     NSLog(@"%s", __PRETTY_FUNCTION__);    
  42. }    
  43. @end    
  44. int main (int argc, const char * argv[])    
  45. {    
  46.       
  47.     @autoreleasepool {    
  48.         // insert code here...    
  49.         //                [[C1 alloc]init]; // 向C1发送消息    
  50.         [[C2 alloc]init]; // 向C2发送消息    
  51.     }    
  52.     return 0;    
  53. }    

 输出:

2012-08-14 23:31:28.834 www[14975:903] +[C1 load]

2012-08-14 23:31:28.837 www[14975:903] +[C2 load]

2012-08-14 23:31:28.837 www[14975:903] +[C1(Hello) load]

2012-08-14 23:31:28.838 www[14975:903] +[C1(Hello) initialize]

2012-08-14 23:31:28.838 www[14975:903] Hello

2012-08-14 23:31:28.839 www[14975:903] +[C2(Hello) initialize]

 

 

 

问题:

1,在倒数第二个代码中,为什么没有执行类中的initialize而是执行Category中的initialize方法??(Category覆盖方法时优先级更高)

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 玉石带久了不亮怎么办 手表带久了不亮怎么办 蜜蜡带久了不亮怎么办 钛钢首饰不亮了怎么办 潘多拉玫瑰金戒指褪色了怎么办 金色手表漆掉了怎么办 玫瑰金表带褪色后怎么办 K金褪色或泛黄怎么办 钛钢玫瑰金变黑怎么办 玫瑰金手镯掉色了怎么办 彩金颜色不亮了怎么办 玫瑰金链子黑了怎么办 18k玫瑰金变黑了怎么办 玫瑰金戒指遇到火变黑怎么办 18k白金发黄了怎么办 18k金掉色后怎么办吗 dw手表金色掉漆怎么办 dw玫瑰金手表褪色怎么办 dw金色表带黑了怎么办 机械表机芯坏了怎么办 银镀玫瑰金褪色怎么办 苹果七p玫瑰金掉漆怎么办 美度镀金表掉色怎么办 吃了发黑的香菇怎么办 脸上的皮肤暗黄怎么办 吃了变黑的香菇怎么办 怀孕喝了玫瑰茶怎么办 孕妇爱喝茉莉茶怎么办 干菊花生虫了该怎么办 黑枸杞放了两年怎么办 来大姨妈喝茶了怎么办 干柠檬片过期了怎么办 山地玫瑰根黑了怎么办 带18k的金过敏怎么办 18k钻戒断了怎么办 18k钻戒戒托变色怎么办 苹果七中间按键脱漆怎么办 苹果手机屏幕边缘掉漆了怎么办 十八k白金变色了怎么办 手机后面掉漆了怎么办 玫瑰金戒指刮花了怎么办