In the previous article "go deep into Cocoa and objects", I have introduced in detail the concepts of Class and Object in ObjC. How can we dynamically create classes at runtime today. 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 classes (const char * name, const char * superclassName) {struct objc_class * meta_class; struct Classes * super_class; struct objc_class * new_class; struct objc_class * root_class; va_list args; // ensure that the parent class has super_class = (struct objc_class *) objc_lookUpClass (superclassName); if (super_class = nil) {return NO;} // ensure that the class to be created does not exist if (Objc_lookUpClass (name )! = Nil) {return NO;} // find the root class, because the isa of meta class points to the meta 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 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 leave the empty method lists, we can then use class_addMethods to add the method 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 super class/3 of meta class, set isa new_class of meta 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 want to use runtime-related functions in the code, you need to import libobjc. dylib and related header files, such as runtime. h ).
In the previous article, we summarized that "ObjC generates two objc_classes for each class definition, one being a common class and the other being metaclass. We can create the two objc_class data structures at runtime, and then use objc_addClass to dynamically create a new class definition .", The above Code shows that 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 performSelector:@selector(report)]; [instanceOfNewClass release]; } return 0;}
In the above Code, we create a subclass NSStringSubclass that inherits from NSString, add the method report to it, and register it in the runtime system, so that we can use this new class. Here, the performSelector is used to send messages to new class objects, which can avoid compilation of warning messages because we have not declared the class and the response messages ).
The execution result is:
>> This object is 0x100114710. >> Class is NSStringSubclass, and super is NSString. >> Following the isa pointer 1 times gives 0x100114410 >> Following the isa pointer 2 times gives 0x100114560 >> 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 0x100114710.
2. class address: 0x100114410
3. The meta class address is 0x100114560.
4. The class address of meta class is 0x7fff7e257b50, which is also the meta class of NSObject)
5. The meta class of NSObject's meta class is its own
Original article: http://www.cnblogs.com/kesalin/archive/2012/01/30/objc_create_class.html