NSObject - еще более интересный зверь, чем ожидалось.Как правило, каждый думает о карте
method_getName: Method -> SEL
как об индивидуальной.Т.е. обычно думают, что method_getName(methodA) == method_getName(methodB)
на всякий случай methodA == methodB
.Рекомендуется подумать так: нельзя создавать класс во время кодирования с помощью @interface
, который имеет несколько методов с одним и тем же селектором, и нельзя добавлять два метода с одним и тем же селектором к классу, использующему class_addMethod()
во время выполнения.
Однако, очевидно, это можно сделать вручную.Следующий код демонстрирует это.Этот код получает все методы экземпляра в NSObject и распечатывает каждый из них с именем «retainWeakReference» или «allowWeakReference», а затем получает все методы class в NSObject и распечатывает каждый из них с именем «initialize» или «load».
uint NSObjectInstanceMethodCount;
Method *NSObjectInstanceMethodArray = class_copyMethodList([NSObject class], &NSObjectInstanceMethodCount);
for (int i = 0; i < NSObjectInstanceMethodCount; i++) {
Method method = *(NSObjectInstanceMethodArray + i);
SEL selector = method_getName(method);
IMP implementation = method_getImplementation(method);
const char *types = method_getTypeEncoding(method);
if (strcmp(selector, "retainWeakReference") == 0 || strcmp(selector, "allowsWeakReference") == 0) {
NSLog(@"NSObject implements method(%s,%p,%s)", selector, implementation, types);
}
}
uint NSObjectClassMethodCount;
Method *NSObjectClassMethodArray = class_copyMethodList(object_getClass([NSObject class]), &NSObjectClassMethodCount);
for (int i = 0; i < NSObjectClassMethodCount; i++) {
Method method = *(NSObjectClassMethodArray + i);
SEL selector = method_getName(method);
IMP implementation = method_getImplementation(method);
const char *types = method_getTypeEncoding(method);
if (strcmp(selector, "initialize") == 0 || strcmp(selector, "load") == 0) {
NSLog(@"metaNSObject implements method(%s,%p,%s)", selector, implementation, types);
}
}
Вывод не соответствует ожидаемому, кроме предыдущего,:
NSObject implements method(retainWeakReference,0x7fff8a120b1f,c16@0:8)
NSObject implements method(allowsWeakReference,0x7fff8a120b05,c16@0:8)
NSObject implements method(retainWeakReference,0x7fff80ad6db0,c16@0:8)
NSObject implements method(allowsWeakReference,0x7fff80ad6d90,c16@0:8)
metaNSObject implements method(load,0x7fff8a09e4f2,v16@0:8)
metaNSObject implements method(initialize,0x7fff8a00cb89,v16@0:8)
metaNSObject implements method(load,0x7fff80a57670,v16@0:8)
metaNSObject implements method(initialize,0x7fff80a133d0,v16@0:8)
Итак, как теперь очевидно, NSObject имеет две реализации для каждого из селекторов -retainWeakReference
, -allowsWeakReference
, +load
и +initialize
.Это только четыре метода в NSObject , для которых существует несколько реализаций, что подтверждается тем фактом, что только четыре из них, о которых сообщается в коде в вопросе, не могут быть добавлены в MyNSObject .
Оператор, который приближается к подсчету в качестве ответа на вопрос, заключается в том, что вы не можете добавить несколько методов с одним и тем же селектором в класс, созданный во время выполнения с помощью class_addMethod()
.В частности, нет, методы не реализуются классом, созданным во время выполнения с objc_allocateClassPair()
«из коробки».