[翻译]Obejective-C的类加载与初始化

来源:互联网 发布:java 嵌入式开发哪个好 编辑:程序博客网 时间:2024/04/28 17:36

作为一个iOS程序员,你一般情况下并不需要关心类是如何加载到内存里的。这是一个复杂的过程,由运行时处理的,并早于你的代码运行。
对于大部分的类,你只需要知道如何使用即可,但是有些时候,你要做一些特殊的处理,比如一个某个类想创建一个全局的表,用来加载本地的用户数据或则其他一些任务。
Objective-C运行时采用两种方式来实现这个需求:+initialize和+load。

+load

如果你在类里实现了这个方法,只要这个类一旦加载,就会触发+load方法。如果你在程序中或程序链接的动态库中实现了该方法,此方法会在main()调用前加载,如果你在可执行的包里实现了load方法,便会在此包加载时执行。

因为load方法执行在程序的早期,因此你必须非常小心。很显然,类的加载有先后,必然有些类早于另外一些类,所以在你在某个类的load方法写代码时,你不能保证其他类已经加载并可以调用。更严重的情况是,你app(框架或插件)中的某些C++的静态初始化器,也许并未开始运行,所以如果你的代码有赖于此,可能会引发崩溃。有一个好的情况是,你链接的框架(.framework)肯定会早于你的类加载,因此你可以放心使用框架里的类。父类也会早于子类被加载,因此你也可以放心的使用父类。有一点需要注意,因为load方法执行时,自动释放池并未创建,因此如果你有用到内存相关的方法,请自己手动创建一个内存管理池。
load方法的一个有趣的功能是,如果你在类别里实现了load方法,在类里也同样实现,他们都会被执行。这和你所知的类别可能有点出入,但是因为load比较特别。这就意味着,你可以在load方法里做一些特别的事情,比如方法交换。

+initialize

initialize方法执行在一个比较稳定的环境,也是比load方法更适合加代码的地方。initialize有趣的地方在于它是懒加载的,甚至永不加载,当一个类加载时候,它不会执行。当给类发送一个消息的时候,这个类就会检测是否已经初始化过了,如果没有,就进行初始化。你可以认为它执行的代码大概如下:

id objc_msgSend(id self, SEL _cmd, ...)    {        if(!self->class->initialized)            [self->class initialize];        ...send the message...    }

当然,实际上肯定比上面的代码复杂,因为涉及到线程安全及其他。因此我们可以知道,一个类的initialize方法只会执行一次,并且会在此类收到第一个消息的时候执行。和load一样,initialize消息会在本类处理前,会先将消息发送给它所有的父类(译者注:load是实现了就会执行,initialize是发送了消息肯定会执行,如果本身没实现,就会执行继承于父类的方法),之后再自己处理消息。
使用initialize会比load更安全,因为不需要太考虑时间点。而且肯定是在UIApplicationmain()之后。
由于initialize的懒运行,因此不适合在里面注册类,
这个特性,让你可以使用initialize更任性,而且你可以不用担心在类加载时候浪费资源。
在使用initialize的时候,你需要注意一点,在我们上面嵌入的代码中,有执行[self->class initialize],这意味着,如果你的类未实现此方法,就会调用继承自父类的initialize方法。正因如此,你最好在代码中加入判断:

 + (void)initialize    {        if(self == [WhateverClass class])        {            ...perform initialization...        }    }

如果你不加入判断,如果有一个子类继承于它,你写的initialize方法可能会执行多次,即时子类没有实现自身的initialize方法。就算你没有子类,但是当你此类使用到苹果的kvo/kvc机制,也会帮你生成一个子类。

原文: http://math.stackexchange.com/

1 0
原创粉丝点击