Objective-C 中 +load 与 +initialize

本文详细介绍了Objective-C中的类加载机制,包括+load和+initialize方法的区别与应用场景,以及它们的执行顺序。通过实例演示了如何利用这两个方法进行类级别的初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



 

类的加载

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覆盖方法时优先级更高)

 

 

CH341A编程器是一款广泛应用的通用编程设备,尤其在电子工程和嵌入式系统开发领域中,它被用来烧录各种类型的微控制器、存储器和其他IC芯片。这款编程器的最新版本为1.3,它的一个显著特点是增加了对25Q256等32M芯片的支持。 25Q256是一种串行EEPROM(电可擦可编程只读存储器)芯片,通常用于存储程序代码、配置数据或其他非易失性信息。32M在这里指的是存储容量,即该芯片可以存储32兆位(Mbit)的数据,换算成字节数就是4MB。这种大容量的存储器在许多嵌入式系统中都有应用,例如汽车电子、工业控制、消费电子设备等。 CH341A编程器的1.3版更新,意味着它可以更多的芯片型号兼容,特别是针对32M容量的芯片进行了优化,提高了编程效率和稳定性。26系列芯片通常指的是Microchip公司的25系列SPI(串行外围接口)EEPROM产品线,这些芯片广泛应用于各种需要小体积、低功耗和非易失性存储的应用场景。 全功能版的CH341A编程器不仅支持25Q256,还支持其他大容量芯片,这意味着它具有广泛的兼容性,能够满足不同项目的需求。这包括但不限于微控制器、EPROM、EEPROM、闪存、逻辑门电路等多种类型芯片的编程。 使用CH341A编程器进行编程操作时,首先需要将设备通过USB连接到计算机,然后安装相应的驱动程序和编程软件。在本例中,压缩包中的"CH341A_1.30"很可能是编程软件的安装程序。安装后,用户可以通过软件界面选择需要编程的芯片类型,加载待烧录的固件或数据,然后执行编程操作。编程过程中需要注意的是,确保正确设置芯片的电压、时钟频率等参数,以防止损坏芯片。 CH341A编程器1.3版是面向电子爱好者和专业工程师的一款实用工具,其强大的兼容性和易用性使其在众多编程器中脱颖而出。对于需要处理25Q256等32M芯片的项目,或者26系列芯片的编程工作,CH341A编程器是理想的选择。通过持续的软件更新和升级,它保持了现代电子技术同步,确保用户能方便地对各种芯片进行编程和调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值