NSObject + load和+ initialize-它们是做什么的? [英] NSObject +load and +initialize - What do they do?

查看:63
本文介绍了NSObject + load和+ initialize-它们是做什么的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有兴趣了解导致开发人员覆盖+ initialize或+ load的情况.文档清楚地表明,Objective-C运行时会为您调用这些方法,但是从这些方法的文档中可以真正看出所有这些. :-)

I'm interested in understanding the circumstances leading a developer to override +initialize or +load. Documentation makes it clear these methods are called for you by the Objective-C runtime, but that's really all that is clear from the documentation of those methods. :-)

我的好奇心来自查看Apple的示例代码-MVCNetworking.他们的模型类具有+(void) applicationStartup方法.它在文件系统上做一些内务处理,读取NSDefaults等等,等等,并且在尝试使用NSObject的类方法之后,似乎可以将这个清洁工作放到+ load中.

My curiosity comes from looking at Apple's example code - MVCNetworking. Their model class has a +(void) applicationStartup method. It does some housekeeping on the filesystem, reads NSDefaults, etc etc... and, after trying to grok NSObject's class methods, it seems like this janitorial work might be okay to put into +load.

我确实修改了MVCNetworking项目,删除了App Delegate中对+ applicationStartup的调用,并将整理位放入+ load ...我的计算机没有着火,但这并不意味着它是正确的!我希望对您必须调用+ load或+ initialize的自定义设置方法周围的任何细微之处,陷阱和其他知识有所了解.

对于+ load文档说:

For +load documentation says:

将加载消息发送到既属于类又属于类别 动态加载和静态链接,但仅当新加载时 类或类别实现了可以响应的方法.

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.

如果您不知道所有单词的确切含义,那么这句话很笨拙且难以解析.救命!

This sentence is kludgey and difficult to parse if you don't know the precise meaning of all the words. Help!

  • 动态加载和静态链接"是什么意思?可以动态加载和静态链接某些东西吗,或者它们是互斥的?

  • What is meant by "both dynamically loaded and statically linked?" Can something be dynamically loaded AND statically linked, or are they mutually exclusive?

"...新加载的类或类别实现了可以响应的方法"什么方法?反应如何?

"...the newly loaded class or category implements a method that can respond" What method? Respond how?

对于+ initialize,文档显示:

As for +initialize, documentation says:

初始化它只能在每个类中调用一次.如果你想表演 类和类别的独立初始化 类,您应该实现加载方法.

initialize it is invoked only once per class. If you want to perform independent initialization for the class and for categories of the class, you should implement load methods.

我的意思是,如果您要尝试设置类,请不要使用initialize."好的.什么时候或为什么要覆盖初始化?

I take this to mean, "if your trying to setup the class... don't use initialize." Okay, fine. When or why would I override initialize then?

推荐答案

load消息

在将类对象加载到进程的地址空间后不久,运行时将load消息发送到每个类对象.对于属于程序的可执行文件的类,运行时会在进程的生命周期的早期非常早地发送load消息.对于共享(动态加载)库中的类,运行时会在将共享库加载到进程的地址空间后立即发送加载消息.

The load message

The runtime sends the load message to each class object, very soon after the class object is loaded in the process's address space. For classes that are part of the program's executable file, the runtime sends the load message very early in the process's lifetime. For classes that are in a shared (dynamically-loaded) library, the runtime sends the load message just after the shared library is loaded into the process's address space.

此外,如果该类对象本身实现了load方法,则运行时仅将load发送到该类对象.示例:

Furthermore, the runtime only sends load to a class object if that class object itself implements the load method. Example:

@interface Superclass : NSObject
@end

@interface Subclass : Superclass
@end

@implementation Superclass

+ (void)load {
    NSLog(@"in Superclass load");
}

@end

@implementation Subclass

// ... load not implemented in this class

@end

运行时将load消息发送到Superclass类对象.即使Subclass继承了Superclass的方法,它也不会将load消息发送到Subclass类对象.

The runtime sends the load message to the Superclass class object. It does not send the load message to the Subclass class object, even though Subclass inherits the method from Superclass.

运行时将load消息发送给该类的所有超类对象(如果这些超类对象实现了load)以及共享库中的所有类对象之后,该运行库将load消息发送给类对象您链接到.但是您不知道自己可执行文件中的哪些其他类还收到了load.

The runtime sends the load message to a class object after it has sent the load message to all of the class's superclass objects (if those superclass objects implement load) and all of the class objects in shared libraries you link to. But you don't know which other classes in your own executable have received load yet.

如果您的进程实现了load方法,则您的进程加载到其地址空间的每个类都会收到一条load消息,而不管您的进程是否对该类进行了其他使用.

Every class that your process loads into its address space will receive a load message, if it implements the load method, regardless of whether your process makes any other use of the class.

作为_class_getLoadMethod的_class_getLoadMethod中的特例,您可以看到运行时如何查找load方法. /objc-runtime-new.mm"rel =" noreferrer> objc-runtime-new.mm ,并直接从

You can see how the runtime looks up the load method as a special case in the _class_getLoadMethod of objc-runtime-new.mm, and calls it directly from call_class_loads in objc-loadmethod.mm.

即使同一类上的多个类别实现了load,运行时也会为其加载的每个类别运行load方法.这很不寻常.通常,如果两个类别在同一个类上定义了相同的方法,则其中一个方法将获胜"并被使用,而另一个方法将永远不会被调用.

The runtime also runs the load method of every category it loads, even if several categories on the same class implement load.  This is unusual.  Normally, if two categories define the same method on the same class, one of the methods will "win" and be used, and the other method will never be called.

运行时,在将第一条消息(loadinitialize除外)发送到类对象或任何类实例之前,运行时在类对象上调用initialize方法.该消息是使用常规机制发送的,因此,如果您的类未实现initialize,但从继承该类的类继承,则您的类将使用其超类的initialize.运行时将首先将initialize发送给类的所有超类(如果尚未发送initialize的超类).

The runtime calls the initialize method on a class object just before sending the first message (other than load or initialize) to the class object or any instances of the class. This message is sent using the normal mechanism, so if your class doesn't implement initialize, but inherits from a class that does, then your class will use its superclass's initialize. The runtime will send the initialize to all of a class's superclasses first (if the superclasses haven't already been sent initialize).

示例:

@interface Superclass : NSObject
@end

@interface Subclass : Superclass
@end

@implementation Superclass

+ (void)initialize {
    NSLog(@"in Superclass initialize; self = %@", self);
}

@end

@implementation Subclass

// ... initialize not implemented in this class

@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        Subclass *object = [[Subclass alloc] init];
    }
    return 0;
}

该程序输出两行输出:

2012-11-10 16:18:38.984 testApp[7498:c07] in Superclass initialize; self = Superclass
2012-11-10 16:18:38.987 testApp[7498:c07] in Superclass initialize; self = Subclass

由于系统懒惰地发送initialize方法,因此除非您的程序实际将消息发送到该类(或子类,或该类的实例或子类的实例),否则一个类将不会收到该消息.到您收到initialize时,过程中的每个类都应该已经收到load(如果适用).

Since the system sends the initialize method lazily, a class won't receive the message unless your program actually sends messages to the class (or a subclass, or instances of the class or subclasses). And by the time you receive initialize, every class in your process should have already received load (if appropriate).

实现initialize的规范方法是:

@implementation Someclass

+ (void)initialize {
    if (self == [Someclass class]) {
        // do whatever
    }
}

此模式的要点是,当Someclass的子类没有实现initialize时,避免重新初始化自身.

The point of this pattern is to avoid Someclass re-initializing itself when it has a subclass that doesn't implement initialize.

运行时在_class_initialize函数中发送initialize消息. ="noreferrer"> objc-initialize.mm .您可以看到它使用objc_msgSend发送它,这是正常的消息发送功能.

The runtime sends the initialize message in the _class_initialize function in objc-initialize.mm. You can see that it uses objc_msgSend to send it, which is the normal message-sending function.

查看 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆