2008 12 15Class pairs and super
objc_super's receiver must be self, not the metaclass. The metaclass is only used in the second param, as a start point in the super method search.
More Objective-C runtime stuff !
Creating new ObjC classes at runtime is straightforward :
- call
objc_allocateClassPairto start creation - call
class_addIvarto add any instance variables - call
objc_registerClassPairto finish up class creation
You can then add methods with class_addMethod. Methods can be added anytime, instance variables can only be added before objc_registerClassPair.
Creating a new ObjC class creates a class pair — a metaclass to hold class methods, a class to hold instance methods. They're really two distinct objects that you can manipulate as such : calling superclass on a metaclass will retrieve a metaclass.
// Plus sign registers a class method (stored in the metaclass) + (void)alloc; // Minus sign registers an instance method (stored in the class) - (id)init;
objc_getClass("NSView") retrieves the class, objc_getMetaClass("NSView") retrieves the metaclass. To add class or instance methods, call class_addMethod with the metaclass or the class.
As super is not runtime, we need to get the metaclass while handling the super call of a runtime-added method — even though we're in a class method, the runtime sets self as the class and not the metaclass. The first param of objc_super is self, the second is the metaclass to use as a start point for method search.
+ (id)allocWithZone:(NSZone*)zone
{
... our custom code ...
// Retrieve the meta class
id metaclass = objc_getMetaClass(class_getName(self));
// Super call
struct objc_super superData = { self, [metaclass superclass] };
return objc_msgSendSuper(&superData, @selector(allocWithZone:), zone);
}
Objective-C 2.0 Runtime Reference
You can also use object_getClass(self) to return either the class or metaclass depending on wether self is an instance of a class or metaclass respectively.