Objective C类方法load和initialize的区别

作者&投稿:岳徐 (若有异议请与网页底部的电邮联系)
Objective C类方法load和initialize的区别~

 先来看看NSObject Class Reference里对这两个方法说明:

  +(void)initialize
  The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.

  +(void)load
  The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
  The order of initialization is as follows:

  All initializers in any framework you link to.
  All +load methods in your image.
  All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
  All initializers in frameworks that link to you.
  In addition:

  A class’s +load method is called after all of its superclasses’ +load methods.
  A category +load method is called after the class’s own +load method.
  In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.

  Apple的文档很清楚地说明了initialize和load的区别在于:load是只要类所在文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么initialize也不会被调用。

  它们的相同点在于:方法只会被调用一次。(其实这是相对runtime来说的,后边会做进一步解释)。

  文档也明确阐述了方法调用的顺序:父类(Superclass)的方法优先于子类(Subclass)的方法,类中的方法优先于类别(Category)中的方法。

  不过还有很多地方是文章中没有解释详细的。所以再来看一些示例代码来明确其中应该注意的细节。

  +(void)load与+(void)initialize初探
  复制代码
  1 +(void)load会引发+(void)initialize
  2 /******* Interface *******/
  3 @interface SuperClass : NSObject
  4 @end
  5
  6 @interface ChildClass : SuperClass
  7 @end
  8
  9 @interface Insideinitialize : NSObject
  10 - (void)objectMethod;
  11 @end
  12
  13 /******* Implementation *******/
  14 @implementation SuperClass
  15
  16 + (void) initialize {
  17 NSLog(@"%@ %s", [self class], __FUNCTION__);
  18 }
  19
  20 + (void) load {
  21 NSLog(@"%@ %s", [self class], __FUNCTION__);
  22 }
  23
  24 @end
  25
  26 @implementation ChildClass
  27
  28 + (void) initialize {
  29 NSLog(@"%@ %s", [self class], __FUNCTION__);
  30 Insideinitialize * obj = [[Insideinitialize alloc] init];
  31 [obj objectMethod];
  32 [obj release];
  33 }
  34
  35 @end
  36
  37 @implementation Insideinitialize
  38
  39 - (void)objectMethod {
  40 NSLog(@"%@ %s", [self class], __FUNCTION__);
  41 }
  42
  43 + (void) initialize {
  44 NSLog(@"%@ %s", [self class], __FUNCTION__);
  45 }
  46
  47 + (void) load {
  48 NSLog(@"%s", __FUNCTION__);
  49 }
  50
  51 @end
  复制代码
  

  这个示例代码中,一个SuperClass实现了+(void)load和+(void)initialize方法(实际上应该算是重写覆盖了NSObject的这两个方法);ChildClass继承于SuperClass,但是只重写+(void)initialize没有+(void)load;Insideinitialize类也有+(void)load和+(void)initialize方法,它在ChildClass的i+(void)initialize方法中被构建出一个对象。类中的每个函数的实现都非常简单,只是输出类名和方法名。除了Insideinitialize的+(void)load方法只输出了类名,没有使用[self class]。

  首先我们在Xcode的项目中只简单import这些类,而不去使用他们的,然后运行项目就会得到下边的结果:

  SuperClass +[SuperClass initialize]
  SuperClass +[SuperClass load]
  Insideinitialize +[Insideinitialize load]
  就像Apple的文档中说的一下,只要有引用runtime就会自动去调用类的+(void)load方法。不过从输出中,我们还发现SuperClass的+(void)initialize也被调用了,而且是在+(void)load之前被执行;而Insideinitialize的+(void)initialize并没有执行。这是因为在SuperClass的+(void)load方法中,我们调用了类的class方法([self class]),这就符合文档中对+(void)initialize的说明:在类的第一个方法被调用前调用。同时也说明runtime对+(void)load的调用并不视为类的第一个方法。而ChildClass因为没有用到,所以+(void)initialize的方法被没有被执行,而且它也没有去执行父类的+(void)load方法(虽然它有继承下该方法)。

别期待便宜的android机子性能能有多好。即使不考虑这些问题,对于那样的大作,厂商首先考虑的也是iOS,盈利高,硬件和平台统一,优化也能做好。Android平台分散,硬件混杂,盈利也远低于iOS,看android市场上的应用,排前面的全是免费的。也就是说,这样的以盈利为主的游戏商,一般都是在iOS上发布游戏,之后看市场反应和移植难度再决定是否发布Android平台的。所以想玩那些游戏就选iOS,iPhone买不起就买iTouch,反正对于游戏来说CPU内存什么的没太大差异。

Objective C类方法load和initialize的区别如下:
1、load是只要类所在文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。
2、如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么initialize也不会被调用。
它们的相同点在于:方法只会被调用一次。

The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.) The runtime sends the initialize message to classes in a thread-safe manner. Superclasses receive this message before their subclasses.

+(void)load

The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
The order of initialization is as follows:
1.All initializers in any framework you link to.
2.All +load methods in your image.
3.All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
4.All initializers in frameworks that link to you.

In addition:
•A class’s +load method is called after all of its superclasses’ +load methods.
•A category +load method is called after the class’s own +load method.

In a custom implementation of load you can therefore safely message other unrelated classes from the same image, but any load methods implemented by those classes may not have run yet.

Apple的文档很清楚地说明了initialize和load的区别在于:load是只要类所在文件被引用就会被调用,而initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目,就不会有load调用;但即使类文件被引用进来,但是没有使用,那么initialize也不会被调用。

它们的相同点在于:方法只会被调用一次。(其实这是相对runtime来说的,后边会做进一步解释)。

文档也明确阐述了方法调用的顺序:父类(Superclass)的方法优先于子类(Subclass)的方法,类中的方法优先于类别(Category)中的方法。

不过还有很多地方是文章中没有解释详细的。所以再来看一些示例代码来明确其中应该注意的细节。

+(void)load与+(void)initialize初探

复制代码
1 +(void)load会引发+(void)initialize
2 /******* Interface *******/
3 @interface SuperClass : NSObject
4 @end
5
6 @interface ChildClass : SuperClass
7 @end
8
9 @interface Insideinitialize : NSObject
10 - (void)objectMethod;
11 @end
12
13 /******* Implementation *******/
14 @implementation SuperClass
15
16 + (void) initialize {
17 NSLog(@"%@ %s", [self class], __FUNCTION__);
18 }
19
20 + (void) load {
21 NSLog(@"%@ %s", [self class], __FUNCTION__);
22 }
23
24 @end
25
26 @imple www.hnnedu.com mentation ChildClass
27
28 + (void) initialize {
29 NSLog(@"%@ %s", [self class], __FUNCTION__);
30 Insideinitialize * obj = [[Insideinitialize alloc] init];
31 [obj objectMethod];
32 [obj release];
33 }
34
35 @end
36
37 @implementation Insideinitialize
38
39 - (void)objectMethod {
40 NSLog(@"%@ %s", [self class], __FUNCTION__);
41 }
42
43 + (void) initialize {
44 NSLog(@"%@ %s", [self class], __FUNCTION__);
45 }
46
47 + (void) load {
48 NSLog(@"%s", __FUNCTION__);
49 }
50
51 @end

复制代码

这个示例代码中,一个SuperClass实现了+(void)load和+(void)initialize方法(实际上应该算是重写覆盖了NSObject的这两个方法);ChildClass继承于SuperClass,但是只重写+(void)initialize没有+(void)load;Insideinitialize类也有+(void)load和+(void)initialize方法,它在ChildClass的i+(void)initialize方法中被构建出一个对象。类中的每个函数的实现都非常简单,只是输出类名和方法名。除了Insideinitialize的+(void)load方法只输出了类名,没有使用[self class]。

首先我们在Xcode的项目中只简单import这些类,而不去使用他们的,然后运行项目就会得到下边的结果:
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]
Insideinitialize +[Insideinitialize load]

就像Apple的文档中说的一下,只要有引用runtime就会自动去调用类的+(void)load方法。不过从输出中,我们还发现SuperClass的+(void)initialize也被调用了,而且是在+(void)load之前被执行;而Insideinitialize的+(void)initialize并没有执行。这是因为在SuperClass的+(void)load方法中,我们调用了类的class方法([self class]),这就符合文档中对+(void)initialize的说明:在类的第一个方法被调用前调用。同时也说明runtime对+(void)load的调用并不视为类的第一个方法。而ChildClass因为没有用到,所以+(void)initialize的方法被没有被执行,而且它也没有去执行父类的+(void)load方法(虽然它有继承下该方法)。

+(void)load和+(void)initialize可当做普通类方法(Class Method)被调用

接着, 在程序中让ChildClass直接调用load:
[ChildClass load];

程序正常运行,并输出了结果:
SuperClass +[SuperClass initialize]
SuperClass +[SuperClass load]
+[Insideinitialize load]
ChildClass +[ChildClass initialize]
Insideinitialize +[Insideinitialize initialize]
Insideinitialize -[Insideinitialize objectMethod]
ChildClass +[SuperClass load]

前面三个结果跟之前一样,不过之后ChildClass的+(void)initialize也被自动执行调用,并且我们可以在其中安全创建出Insideinitialize类并使用它,而Insideinitialize因为调用alloc方法是第一次使用类方法, 所以激发了Insideinitialize的+(void)initialize。

另一个方面,ChildClass继承下了+(void)load而且可以被安全地当做普通类方法(Class Method)被使用。这也就是我之前所说的load和initialize被调用一次是相对runtime而言(比如SuperClass的initialize不会因为自身load方法调用一次,又因为子类调用了load又执行一次),我们依然可以直接去反复调用这些方法。

子类会调用父类的+(void)initialize

接下来,我们再修改一下SuperClass和ChildClass:去掉SuperClass中的+(void)load方法;让ChildClass来重写+(void)load,但是去掉+(void)initialize。


樟树市13777451297: Objective - C 类方法 load 和 initialize 的区别 -
仉视谷氨: 先来看看NSObject Class Reference里对这两个方法说明: +(void)initialize The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first messag...

樟树市13777451297: 怎么在objective - c中一个类的类方法 -
仉视谷氨: +(void)showNameOfClass(Class class);这样写,先加号+,然后返回值,然后方法名,然后参数列表

樟树市13777451297: 浅谈OC中方法和函数的区别? -
仉视谷氨: 标签:class style com 使用 http si it 文件 la 方法:方法是Objective-C独有的一种结构,只能在Objective-C中声明、定义和使用,C语言不能声明、定义和使用.1、类方法以+号开头,对象方法以-号开头+ (void) init; // 类方法- (void) show...

樟树市13777451297: objective - c 实例方法\类方法如何调用 -
仉视谷氨: 在书写了类的声明和实现后,应用程序如何去调用它呢? 在Objective-c中,调用方法的简单格式如下: 1[实例 方法]; 如: [person setAge:32]; 其中 person是Person类的实例. 或者是: 2 [类名 方法名]; 如:NSString str = [NSDate date]; ...

樟树市13777451297: objective - c中类方法和对象方法有什么区别? -
仉视谷氨: 类方法属于类级别的,为该类所有对象所共享 可以用类名调用,也可以用某实例化的对象名调用 实例方法属于具体某个实例化对象的,只能用对象名调用 类方法就像是类的静态函数,对内的成员做一些操作,操作结果被类整体生效 对象方法是对某个对象自身的操作.

樟树市13777451297: objective - c 中如何在一个函数中调用自己类中的另外一个函数 -
仉视谷氨: Objective-c方法调用流程Objective-c是一门动态语言,动态两个字主要就体现在我们调用方法的时候,运行时回动态的查找方法,然后调用相应的函数地址.运行时是整个Objective-c程序的基石,有了它我们的程序才能正常运行起来....

樟树市13777451297: Objective - C 具有多个参数的方法 -
仉视谷氨: 一个冒号一个参数,例如- (void)FunctionArg1:(id)arg1 Arg2:(id)arg2 就相当于c语言中的 void FunctionArg1Arg2(void *arg1, void *arg2)

樟树市13777451297: objective - c中float类型变量和byte数组之间相互转换,怎么实现,求指导? -
仉视谷氨: 不是很懂OC,C语言里 是通过联合体方式,或者内存拷贝 比如 float a = 1000.1f ; int len = sizeof(float); byte* pBuf = new byte[len]; memcpy(&a,pBuf,len); 或者union { float num ; byte buf[sizeof(float)]; }

樟树市13777451297: 为什么 Objective - C 很难 -
仉视谷氨: Objective-C 比 C 简单,比C 方便 个人认为,Objective-C只是 C 的子集(理念上这么认为,实际上他们是不同的语言),然后让C 里面一些可选的框架,比如COM,全局统一基类,在objc中成为标配.如果你是从C入门,然后学了C ,再过来...

樟树市13777451297: Objective - C中如何创建构造函数呢? -
仉视谷氨: 在objective-c中与使用很多其他的oop语言一样,可以使用构造函数,他是在创建对象的时候用来初始化对象数据的一种特殊的方法.构造函数可以使用任何方式命名,但是通常,将他们命名为Init.构造方法返回对象的一个指针,可以通过调用...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网