Objective-C的Initialize初始化方法研究
这篇文章介绍了Objective-C比较底层的内容,主要讲解initialize和init方法的区别。从这篇文章中我们不光可以了解Objective-C在初始化时所做的事情,更可以学习到一些如何研究Objective-C语言内部到底做了什么的方法,这样你也可以自己对更深层次的内容进行探寻。
Objective-C很有趣的一个地方是,它非常非常像C。实际上,它就是C语言加上一些其他扩展和一个运行时间(runtime)。
有了这个在每个Objective-C程序中都会起作用的附加运行时间,给了它一些动态的特性。C和C++没有运行时间,他们仅仅被编译为完全按照代码的顺序去执行,不多也不少。
Objective-C中带有运行时间的好处是,它可以在你的程序运行的流程中进行参与。在Objective-C中,它包括检查是否一个对象可以处理特定的消息,如果不能处理,它就帮助你自动调用其他特定的方法去完成。
initialize不是init
运行时间的行为之一就是initialize。虽然看起来有点像大家常见的init,但是他们并不相同。
在程序运行过程中,它会在你程序中每个类调用一次initialize。这个调用的时间发生在你的类接收到消息之前,但是在它的超类接收到initialize之后。
举个例子,比如一个叫做Duck的类:
#import "Duck.h";
@implementation Duck
+(void) initialize {
NSLog(@"Duck initialize");
}
-(void) init {
NSLog(@"Duck init");
}
@end
我们在这里记录initialize和init调用的时间。
我们建立三个Duck对象的实例:
Duck* duck1 = [[Duck alloc] init];
Duck* duck2 = [[Duck alloc] init];
Duck* duck3 = [[Duck alloc] init];
看一下记录:
2008-03-23 20:03:25.871 initialize_example[30253:10b] Duck initialize
2008-03-23 20:03:25.872 initialize_example[30253:10b] Duck init
2008-03-23 20:03:25.873 initialize_example[30253:10b] Duck init
2008-03-23 20:03:25.873 initialize_example[30253:10b] Duck init
我们可以看到,虽然我们创建了3个Duck的实例,但是 initialize仅仅被调用了一次。我们也可以看到,直到我们创建了一个Duck的实例,initialize才被调用。
但是如果Duck有一个子类的话,比如我们建一个Duck的子类叫做Chicken(好怪异……):
#import <cocoa /Cocoa.h>
#import "Duck.h"
@interface Chicken : Duck {
}
@end
注意Chicken这个类并没有实现initialize方法。
如果我们同样运行这个程序,但是加上一个Chicken的实例:
Duck* duck1 = [[Duck alloc] init];
Duck* duck2 = [[Duck alloc] init];
Duck* duck3 = [[Duck alloc] init];
Chicken* chicken = [[Chicken alloc] init];
我们期待看到4个Duck的init调用(因为我们建立了3个Duck和一个Chicken),但是我们看到了这样情况:
2008-03-23 20:13:34.698 initialize_example[30408:10b] Duck initialize
2008-03-23 20:13:34.699 initialize_example[30408:10b] Duck init
2008-03-23 20:13:34.700 initialize_example[30408:10b] Duck init
2008-03-23 20:13:34.700 initialize_example[30408:10b] Duck init
2008-03-23 20:13:34.700 initialize_example[30408:10b] Duck initialize
2008-03-23 20:13:34.701 initialize_example[30408:10b] Duck init
我们看到了4个Duck的init和2个Duck的initialize方法。这是怎么回事呢?
看来如果一个子类没有实现initialize方法,那么超类会调用这个方法两次,一次为自己,而一次为子类。
我们在Duck的initialize类中记录一下类名,这样可以看得更清楚:
+(void) initialize {
NSLog(@"Duck initialize class:%@", [self class]);
}
运行结果如下:
2008-03-23 20:21:08.818 initialize_example[30513:10b] Duck initialize class:Duck
2008-03-23 20:21:08.819 initialize_example[30513:10b] Duck init
2008-03-23 20:21:08.820 initialize_example[30513:10b] Duck init
2008-03-23 20:21:08.820 initialize_example[30513:10b] Duck init
2008-03-23 20:21:08.820 initialize_example[30513:10b] Duck initialize class:Chicken
2008-03-23 20:21:08.821 initialize_example[30513:10b] Duck init
如果你希望确定只用了initialize一次用来实现某些单独运行的工作,或者希望实现仅仅运行一次的方法,检查一下[self class],才能确定是否是你希望做到的效果。
使用技巧和技术
initialize类方法中的代码只执行一次,它是类里面第一个被调用的方法。我们通常利用该方法来设置类的版本号(请参考“版本化和兼容性”一节)。
对于继承链中的每一个类,不论其是否实现initialize方法,运行时都会向它发送initialize消息。这可能导致一个类的initialize方法被多次调用(举个例子,如果子类没有实现initialize方法,则其父类的方法将被调用两次)。但通常您希望始化代码仅执行一次,为确保如此,您可以执行如下检查:
if (self == [NSFoo class]) {
// the initializing code
}
不应该显式地调用initialize方法。
参考资料来源:
http://www.cocoachina.com/b/?p=132
http://www.apple.com.cn/developer/mac/library/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/FrameworkImpl.html#/apple_ref/doc/uid/20001286
分享到:
相关推荐
3. **构造方法(Init Methods)**:初始化方法如`-init`,`-initWithCoder:`和`-initWithNibName:bundle:`用于创建并设置新对象的状态。 4. **分类(Categories)**:使用`+load`和`+initialize`方法,可以在类加载...
Objective-C 中的构造器主要用于初始化对象。一个典型的构造器如下: ```objective-c - (Fraction *)initWithNumerator:(int)n denominator:(int)d { self = [super init]; // 调用父类的构造器 if (self) { ...
4. 对象初始化和析构:Objective-C 2.0改进了对象初始化过程,引入了`-init`方法的快速失败机制,以及`+load`和`+initialize`方法,用于类加载时的自定义行为。 三、内存管理与ARC Objective-C 2.0引入了自动引用...
在Objective-C中,`+load`和`+initialize`是两个非常重要的类方法,它们在类的生命周期中扮演着特定的角色。这两个方法都是在类被加载到内存中时调用,但它们的调用时机和用途有所不同。接下来,我们将详细探讨这两...
在iOS和Objective-C(OC)开发中,"load"和"initialize"是两个重要的类方法,它们在程序启动时被自动调用,用于执行一些初始化操作。了解并正确使用这两个方法对于优化应用性能和实现优雅的初始化逻辑至关重要。 ...
- `initialize` 方法在类第一次收到消息时调用,通常用于类的初始化设置。每个类只会调用一次,子类的`initialize`会先于父类的`initialize`执行。 5. **关联对象(Associated Objects)**: 关联对象允许我们在...
在Objective-C(简称OC)编程语言中,`+load`和`+initialize`是两个非常重要的类方法,它们在程序运行期间起到了初始化类的作用。理解并恰当使用这两个方法,能够帮助开发者更好地控制类的加载和初始化时机,实现...
在iOS开发中,`-(void)load`方法是Objective-C中的一个特殊方法,它与类的加载和初始化过程紧密相关。这个方法在类或者category被加载到内存时会被自动调用,无需显式调用。了解`load`方法的工作原理和应用场景对于...
5. **Category的+load和+initialize方法**: 这两个方法会在类加载到内存时自动调用,可以用来初始化类或者进行一些早期的设置,比如动态添加方法。 在实际开发中,掌握Objective-C的运行时特性和动态添加方法的知识...
例如,`NSObject`是所有Objective-C类的基类,它的`+load`和`+initialize`方法在类加载时被调用,可以用来实现类级别的初始化逻辑。`NSMethodSignature`对象描述了一个方法的参数和返回值类型,而`NSInvocation`则...
12. **load方法**:类和category都包含一个load方法,该方法在类被加载到内存时调用,可用于执行初始化操作。与+initialize不同,load方法的调用顺序是确定的。 13. **App启动流程**:App启动时会经历main函数、...
// 定义SDK的初始化方法 public void Initialize(string apiKey) { // 在这里实现SDK的初始化逻辑 } // 其他SDK相关方法,如展示广告、处理事件等 } ``` 3. **桥接头文件(LsSdkConector.h)**:为了使...
5. **Category的分类加载**:Category中的`+load`方法会在类被加载到内存时自动调用,可用于初始化Category,解决方法冲突等问题。而`+initialize`则在类第一次被使用时调用,适合进行类的准备工作。 6. **Category...
首先,我们需要声明一个静态变量来保存单例实例,然后在`+initialize`方法中初始化这个实例。`+initialize`是类加载时自动调用的方法,确保了在多线程环境下的线程安全。同时,我们还需要阻止其他方式的实例化,通常...
它在Objective-C和Swift中自动跟踪并管理应用程序的内存使用,允许开发者不再手动调用`retain`和`release`方法。这样做的好处是可以降低程序崩溃和内存泄漏的风险,减轻开发者的负担,并提高程序的性能和可预测性。...
2. **创建代理对象**: 初始化完成后,你可以创建`RequestProxy`实例,通过这个代理对象调用远程服务的方法。例如: ```objc RequestPrxy* proxy = [RequestPrxy proxyWithEndpoint:@"tcp -h server_host -p server_...
**MOEAD算法详解** MOEAD(Multi-Objective Evolutionary Algorithm Based on Decomposition,基于分解的多目标进化..."multistep_initialize"文件的细节揭示了算法的初始化阶段,这是整个优化过程中至关重要的一步。
- `initialize_variables.m` 文件实现了种群的初始化,随机生成初始解以开始进化过程。 6. **种群可视化**: - `plot_objective.m` 文件处理了目标函数的绘图,帮助用户直观地理解算法的运行效果,如帕累托前沿的...
% 针对不同的初始化选项得到初始聚类中心,聚类中心为C,大小为k*p case 'uniform' % unifrnd 生成均匀随机数 C = unifrnd(Xmins(ones(k,1),:), Xmaxs(ones(k,1),:)); % For 'cosine' and 'correlation', these ...