Во время выполнения легко создать копию MyNSObject класса Class NSObject:
Сначала создайте новую пару классов .
Class MyNSObject = objc_allocateClassPair(nil, "MyNSObject", 0);
Во-вторых, прочитайте методы, протоколы и переменные из NSObject и добавьте их в новый класс.
uint instanceMethodCount;
Method *instanceMethodArray = class_copyMethodList([NSObject class], &instanceMethodCount);
for (int i = 0; i < instanceMethodCount; i++) {
Method method = *(instanceMethodArray + i);
SEL selector = method_getName(method);
IMP implementation = method_getImplementation(method);
const char *types = method_getTypeEncoding(method);
BOOL success = class_addMethod(MyNSObject, selector, implementation, types);
}
free(instanceMethodArray);
uint protocolCount;
Protocol **protocolArray = class_copyProtocolList([NSObject class], &protocolCount);
for (int i = 0; i < protocolCount; i++) {
Protocol *protocol = *(protocolArray + i);
BOOL success = class_addProtocol(MyNSObject, protocol);
}
free(protocolArray);
uint ivarCount;
Ivar *ivarArray = class_copyIvarList([NSObject class], &ivarCount);
for (int i = 0; i < ivarCount; i++) {
Ivar ivar = *(ivarArray + i);
const char *name = ivar_getName(ivar);
const char *typeEncoding = ivar_getTypeEncoding(ivar);
NSUInteger size, alignment;
NSGetSizeAndAlignment(typeEncoding, &size, &alignment);
BOOL success = class_addIvar(MyNSObject, name, size, alignment, typeEncoding);
}
free (ivarArray);
В-третьих, прочитайте методы из метакласса NSObject и добавьте их в новый метакласс.
uint classMethodCount;
Method *classMethodArray = class_copyMethodList(object_getClass([NSObject class]), &classMethodCount);
for (int i = 0; i < classMethodCount; i++) {
Method method = *(classMethodArray + i);
SEL selector = method_getName(method);
IMP implementation = method_getImplementation(method);
const char *types = method_getTypeEncoding(method);
BOOL success = class_addMethod(object_getClass(MyNSObject), selector, implementation, types);
}
free(classMethodArray);
И, наконец, зарегистрируйте пару классов.
objc_registerClassPair(MyNSObject);
Ну, это почти так просто. Есть несколько проблем с этим. Ну пару пар. Если бы мы добавили следующие строки в конце, но внутри первого блока for
if (!success) {
NSLog(@"unable to add method with selector named %@ to class MyNSObject", NSStringFromSelector(selector));
}
и следующие строки в конце, но в последнем блоке for
if (!success) {
NSLog(@"unable to add method with selector name %@ to metaclass MyNSObject", NSStringFromSelector(selector));
}
Тогда мы увидим следующий вывод:
unable to add method with selector name retainWeakReference to class MyNSObject
unable to add method with selector name allowsWeakReference to class MyNSObject
unable to add method with selector name load to metaclass MyNSObject
unable to add method with selector name initialize to metaclass MyNSObject
Что здесь происходит? Реализуют ли классы (соответственно метаклассы) keepWeakReference и allowWeakReferenc (соответственно загрузку и инициализацию) «из коробки»?
Ссылки: 1. Какао с любовью - Что такое метакласс в Objective-C?
2. Stack Overflow — ответ Джастина Шпар-Саммерса на вопрос "Как можно можно получить размер типа, для которого есть кодировка?"