In Objective-c, NSObject is the root class, and the first two methods in NSObject.h's header file are load and initialize two class methods, and the two methods are described and sorted out in this article.
0. Overview
Objective-c, as an object-oriented language, has the concept of classes and objects. Once compiled, class-related data structures are persisted in the target file and parsed and used at run time. When the application is running, the class information is loaded and initialized.
In fact, there are similar processes in the Java language, and the ClassLoader of the JVM also loads, joins, initializes the classes.
Just as application has a lifecycle callback method, you can also receive a method callback when the class of objective-c is loaded and initialized, and you can do some custom processing where appropriate. And that's what the load and initialize methods can do for us.
1 + (void) load; 2 + (void) initialize;
You can see that both methods are class methods that begin with "+" and return empty. In general, we may not need to look at these two methods during development. If there is a need to customize, we can give the implementation of these two methods in the custom NSObject subclass so that the custom method can be called during the loading and initialization of the class.
From the above statement, perhaps these two methods and other class methods compared to nothing special. However, these two methods have a certain "particularity", which is the reason that these two methods are often put together specifically mentioned. For details, please see the following subsections of the arrangement.
1. Common features of load and initialize
Load and initialize have a lot in common, so here's a simple list:
The system will call at most once without considering the developer's active use
If both the parent and child classes are called, the invocation of the parent class must precede the child class
To create the right run environment in advance of the application run
Do not rely heavily on these two methods when you use them, unless you really need to
2. Key points of the Load method
Nonsense not much to say, directly on the Essentials list:
The calling time is early and the operating environment is uncertain. Specifically, it is usually loaded on iOS when the app is launched, but when the load is called, there is no guarantee that all classes will be loaded and available, and that you are responsible for auto release when necessary.
To add the above point, for the two libraries that have dependencies, the load of the dependent classes is called first. But within a library, the order of calls is indeterminate.
For a class, no implementation of the Load method is called, and inheritance of NSObject is not considered.
The load method of a class does not specify [super Load], the parent class receives the call, and precedes the subclass.
The category load will also receive calls, but in order after the main class's load call.
Initialize calls are not triggered directly.
3. Key points of the Initialize method
Similarly, the main points of direct finishing:
Initialize's natural invocation is the first time the current class is actively used (lazy, which resembles the Java class's "Clinit").
When the Initialize method receives the call, the operating environment is basically sound.
Initialize is guaranteed to be thread-safe during operation.
Unlike load, even if a subclass does not implement the Initialize method, it inherits the implementation of the parent class and invokes it again. Note that before this, the method of the parent class has been executed once, and no super call is required.
Due to these characteristics of initialize, the application is slightly more extensive than load. Can be used to do some initialization work, or a singleton mode of implementation of the scheme.
4. Principle
"There is no secret in front of the source." Finally, let's look at some of the source code that Apple is opening up. From this we may be able to understand why load and initialize and invocation are some of the features.
Where load is called in a load_images function in the OBJC library, the header information in the binary image file is taken out, the class definition information in each module is parsed and read, the class and category of the Load method are recorded, and finally the call is uniformly executed.
The Prepare_load_methods function is implemented as follows:
1 voidPrepare_load_methods (Header_info *hi)2 {3 Module mods;4UnsignedintMidx;5 if(_objcheaderisreplacement (HI)) {6 return;7 }8 9Mods = hi->mod_ptr;Ten for(Midx =0; Midx < hi->mod_count; Midx + =1) One { AUnsignedintindex; - - if(Mods[midx].symtab = =Nil) the Continue; - - for(index =0; Index < mods[midx].symtab->cls_def_cnt; Index + =1) - { +Class CLS = (Class) mods[midx].symtab->Defs[index]; - if(Cls->info &cls_connected) { + Schedule_class_load (CLS); A } at } - } -Mods = hi->mod_ptr; - -Midx = (unsignedint) hi->Mod_count; - while(midx-->0) { inUnsignedintindex; -UnsignedintTotal ; toSymtab Symtab =Mods[midx].symtab; + - if(Mods[midx].symtab = =Nil) the Continue; *Total = mods[midx].symtab->cls_def_cnt + $Mods[midx].symtab->cat_def_cnt;Panax Notoginseng -index =Total ; the while(index--> mods[midx].symtab->cls_def_cnt) { +Old_category *cat = (old_category *) symtab->Defs[index]; A add_category_to_loadable_list (category) cat; the } + } -}
This is probably why the load method in the main class precedes category. And look at the following paragraph:
1 Static void Schedule_class_load (class CLS) 2 {3 if return ; 4 if (Cls->superclass) schedule_class_load (cls->superclass); 5 add_class_to_loadable_list (CLS); 6 Cls->info |= cls_loaded; 7 }
This is the reason that the parent load method takes precedence over the subclass invocation.
Then look at the initialize call the relevant source code. There is a _class_initialize method implemented in the OBJC library, as follows:
1 void_class_initialize (class CLS)2 {3ASSERT (!cls->Ismetaclass ());4 5 Class supercls;6BOOL reallyinitialize =NO;7 8Supercls = cls->superclass;9 if(Supercls &&!supercls->isinitialized ()) {Ten _class_initialize (SUPERCLS); One } A -Monitor_enter (&classinitlock); - if(!cls->isinitialized () &&!cls->isinitializing ()) { theCls->setinitializing (); -Reallyinitialize =YES; - } -Monitor_exit (&classinitlock); + - if(reallyinitialize) { + _setthisthreadisinitializingclass (CLS); A at if(printinitializing) { -_objc_inform ("initialize:calling +[%s INITIALIZE]", -Cls->nameforlogging ()); - } - -((void(*(Class, SEL)) (Objc_msgsend) (CLS, sel_initialize); in - if(printinitializing) { to_objc_inform ("initialize:finished +[%s INITIALIZE]", +Cls->nameforlogging ()); - } the *Monitor_enter (&classinitlock); $ if(!supercls | | Supercls->isinitialized ()) {Panax Notoginseng _finishinitializing (CLS, supercls); -}Else { the _finishinitializingafter (CLS, supercls); + } AMonitor_exit (&classinitlock); the return; + } - $ Else if(cls->isinitializing ()) { $ if(_thisthreadisinitializingclass (CLS)) { - return; -}Else { theMonitor_enter (&classinitlock); - while(!cls->isinitialized ()) {WuyiMonitor_wait (&classinitlock); the } -Monitor_exit (&classinitlock); Wu return; - } About } $ - Else if(cls->isinitialized ()) { - return; - } A + Else { the_objc_fatal ("Thread-safe class init in OBJC runtime is buggy!"); - } $}
In this code, we can see the sequence of calls and thread security of initialize.
Load and initialize methods for NSObject