使用runtime获取类的方法和变量
获取属性和变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void ycObjc_copyIvar_copyProperies(Class pClass){ unsigned int count = 0; Ivar *ivars = class_copyIvarList(pClass, &count); for (unsigned int i=0; i < count; i++) { Ivar const ivar = ivars[i]; const char*cName = ivar_getName(ivar); NSString *ivarName = [NSString stringWithUTF8String:cName]; NSLog(@"class_copyIvarList:%@",ivarName); } free(ivars);
unsigned int pCount = 0; objc_property_t *properties = class_copyPropertyList(pClass, &pCount); for (unsigned int i=0; i < pCount; i++) { objc_property_t const property = properties[i]; NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)]; NSLog(@"class_copyProperiesList:%@",propertyName); } free(properties); }
|
获取方法列表
1 2 3 4 5 6 7 8 9 10 11 12
| void ycObjc_copyMethodList(Class pClass){ unsigned int count = 0; Method *methods = class_copyMethodList(pClass, &count); for (unsigned int i=0; i < count; i++) { Method const method = methods[i]; //获取方法名 NSString *key = NSStringFromSelector(method_getName(method)); NSLog(@"Method, name: %@", key); } free(methods); }
|
其他runtime方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const char *className = class_getName(pClass);
Class metaClass = objc_getMetaClass(className);
Method method = class_getInstanceMethod(pClass, @selector(someFunc));
Method method = class_getClassMethod(pClass, @selector(someFunc));
IMP imp = class_getMethodImplementation(pClass, @selector(someFunc));
|
一些思考
定义一个 Person
类如下,并取得该类的类和元类,判断以下代码是否能获取到方法
1 2 3 4 5 6 7 8 9 10
| @interface Person : NSObject - (void)instanceFunc; + (void)classFunc; @end
=======
Person *person = [Person alloc]; Class pClass = object_getClass(person); Class metaClass = objc_getMetaClass(className);
|
class_getInstanceMethod
1 2 3 4 5 6 7
| Method method1 = class_getInstanceMethod(pClass, @selector(instanceFunc)); Method method2 = class_getInstanceMethod(metaClass, @selector(instanceFunc));
Method method3 = class_getInstanceMethod(pClass, @selector(classFunc)); Method method4 = class_getInstanceMethod(metaClass, @selector(classFunc));
|
class_getClassMethod
1 2 3 4 5 6 7
| Method method1 = class_getClassMethod(pClass, @selector(instanceFunc)); Method method2 = class_getClassMethod(metaClass, @selector(instanceFunc));
Method method3 = class_getClassMethod(pClass, @selector(classFunc)); Method method4 = class_getClassMethod(metaClass, @selector(classFunc));
|
1 2 3 4 5 6 7
| IMP imp1 = class_getMethodImplementation(pClass, @selector(instanceFunc)); IMP imp2 = class_getMethodImplementation(metaClass, @selector(instanceFunc));
IMP imp3 = class_getMethodImplementation(pClass, @selector(classFunc)); IMP imp4 = class_getMethodImplementation(metaClass, @selector(classFunc));
|
为什么获取元类的类方法仍然可以获取到方法?
查看objc源码可知可以看到底层获取了 cls->getMeta()
的 instance 方法
1 2 3 4 5 6
| Method class_getClassMethod(Class cls, SEL sel) { if (!cls || !sel) return nil;
return class_getInstanceMethod(cls->getMeta(), sel); }
|
继续查看 getMeta 方法
1 2 3 4
| Class getMeta() { if (isMetaClassMaybeUnrealized()) return (Class)this; else return this->ISA(); }
|
如果判断是元类的时候,会返回this, 所以对元类获取类方法仍然可以获取到方法
为什么class_getMethodImplementation获取不存在的方法也会返回值?
直接看源码
1 2 3 4 5 6 7 8 9 10 11 12 13
| __attribute__((flatten)) IMP class_getMethodImplementation(Class cls, SEL sel) { IMP imp; if (!cls || !sel) return nil; lockdebug_assert_no_locks_locked_except({ &loadMethodLock }); imp = lookUpImpOrNilTryCache(nil, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER); if (!imp) { return _objc_msgForward; } return imp; }
|
当imp找不到时会返回 _objc_msgForward