In-depth introduction to the dynamic creation class of cocoa Luo chaohui (http://www.cnblogs.com/kesalin) This article follows the "signature-non-commercial use-consistency" creation public agreement
In the previous articleIn-depth introduction to cocoa and other objectsIn this article, I have introduced in detail
The concept of class and object. How can we run it today?
Dynamically create a class. The following function applies the class and metaclass concepts mentioned above to dynamically create a class at runtime. This function is from inside Mac OS X-the objective-C programming language.
# Import <objc/objc. h>
# Import <objc/runtime. h>
Bool createclassdefinition ( Const Char * Name, Const Char * Superclassname)
{
Struct Objc_class * meta_class;
Struct Objc_class * super_class;
Struct Objc_class * new_class;
Struct Objc_class * root_class;
Va_list ARGs;
// Ensure that the parent class exists
Super_class = (Struct Objc_class *) objc_lookupclass (superclassname );
If (Super_class = nil)
{
Return No;
}
// Make sure the class to be created does not exist
If (Objc_lookupclass (name )! = Nil)
{
Return No;
}
// Find the root class because the ISA of the Meta class points to the Meta class of the root class.
Root_class = super_class;
While (Root_class-> super_class! = Nil)
{
Root_class = root_class-> super_class;
}
// Allocate memory for the class and its Meta class
New_class = calloc ( 2 , Sizeof ( Struct Objc_class ));
Meta_class = & new_class [ 1 ];
// Set class
New_class-> ISA = meta_class;
New_class-> info = cls_class;
Meta_class-> info = cls_meta;
// Copy the class name. To improve the efficiency, both the class and Meta class point to the same class name string.
New_class-> name = malloc (strlen (name) + 1 );
Strcpy ((Char *) New_class-> name, name );
Meta_class-> name = new_class-> name;
// Assign and set the null method lists. We can use class_addmethods to add a method to the class later.
New_class-> methodlists = calloc ( 1 , Sizeof ( Struct Objc_method_list *));
Meta_class-> methodlists = calloc ( 1 , Sizeof ( Struct Objc_method_list *));
// Add the class to the inheritance system:
// 1. Set the super class of the class.
// 2. Set the super class of the Meta class.
// 3. Set Isa for Meta class
New_class-> super_class = super_class;
Meta_class-> super_class = super_class-> ISA;
Meta_class-> ISA = ( Void *) Root_class-> ISA;
// Finally, register the class to the runtime system.
Objc_addclass (new_class );
Return Yes;
}
If you wantCodeTo use the runtime-related functions, we need to import libobjc. dylib and import the relevant header files (such as the runtime. h here ).
In Previous Article Summary to" Objc
Generate two objc_class for each class definition. One is a common class and the other is metaclass. We can create the two objc_class data structures at runtime, and then use objc_addclass to dynamically create a new class definition. ", Which is reflected in the above Code: new_class and meta_class are the two objc_classes required by the new class. Other codes are not explained. Comments and codes are self-explanatory.
In actual use, we use the objc runtime function to dynamically create classes:
Class objc_allocateclasspair (class superclass,Const Char* Name, size_t extrabytes );
For example:
# Import <objc/objc. h>
# Import <objc/runtime. h>
Void Reportfunction (ID self, Sel _ cmd)
{
Nslog ( @" > This object is % P. " , Self );
Nslog ( @" > Class is % @, and super is % @. " , [Self Class ], [Self superclass]);
Class prevclass = NULL;
Int Count = 1 ;
For (Class currentclass = [self Class ]; Currentclass; ++ count)
{
Prevclass = currentclass;
Nslog ( @" > Following the ISA pointer % d times gives % P " , Count, currentclass );
Currentclass = object_getclass (currentclass );
If (Prevclass = currentclass)
Break ;
}
Nslog ( @" > Nsobject's class is % P " , [Nsobject Class ]);
Nslog ( @" > Nsobject's Meta class is % P " , Object_getclass ([nsobject Class ]);
}
Int Main ( Int Argc, Const Char * Argv [])
{
@ Autoreleasepool
{
Class newclass = objc_allocateclasspair ([nsstring Class ], " Nsstringsubclass " , 0 );
Class_addmethod (newclass, @ selector (report), (IMP) reportfunction, " V @: " );
Objc_registerclasspair (newclass );
Id instanceofnewclass = [[newclass alloc] init];
[Instanceofnewclass extends mselector: @ selector (report)];
[Instanceofnewclass release];
}
Return 0 ;
}
In the above Code, we create a subclass that inherits from nsstring.NsstringsubclassAnd then add a method to it.
Report, and register it in the runtime system, so that we can use this new class. Here, the performselector is used to send messages to the new class object, which can avoid compilation of warning messages (because we have not declared the class and its responsive messages ).
The execution result is:
> This Object Is Zero X 100114710 .
> Class Is Nsstringsubclass, and super Is Nsstring.
> Following the ISA pointer 1 Times gives Zero X 100114410
> Following the ISA pointer 2 Times gives Zero X 100114560
> Following the ISA pointer 3 Times gives 0x7fff7e257b50
> Nsobject ' S Class is 0x7fff7e257b78
> Nsobject ' S Meta class is 0x7fff7e257b50
Based on the class relationship diagram above, it is not difficult to analyze the internal class structure of nsstringsubclass from the execution results:
1. The object address is: Zero X 100114710
2. The class address is: Zero X 100114410
3. The Meta class address is: Zero X 100114560
4. The class address of the Meta class is: 0x7fff7e257b50 (Also
Nsobject Meta class)
5. nsobject's Meta classMeta class isItself