Runtime获取类的属性列表和方法列表
Runtime很强大,他使得OC中没有真正意义上的私有属性和私有方法,我们可以利用OC的运行时拿到一个类的任何方法和任何属性,然后动态的去调用方法,objc_megsend(),甚至可以在运行时动态的为一个类去添加属性和方法,此篇博客要学习的是两个知识点:
- 获取对象的所有属性
- 获取对象的所有方法
为了方便,我们可以在项目中为NSObject添加一个category,增加下面两个方法,这样我们就可以轻轻松松获得每个类的所以方法和所以属性了,记得导入runtime的头文件哦。
获取对象的所有属性、方法、属性和属性内容
NSObject+JGRuntime.h文件
#import <Foundation/Foundation.h>
@interface NSObject (JGRuntime)
/* 获取对象的所有属性 */
+(NSArray *)getAllProperties;
/* 获取对象的所有方法 */
+(NSArray *)getAllMethods;
/* 获取对象的所有属性和属性内容 */
+ (NSDictionary *)getAllPropertiesAndVaules;
@end
NSObject+JGRuntime.m文件
#import "NSObject+JGRuntime.h"
#import <objc/runtime.h>
@implementation NSObject (JGRuntime)
/* 获取对象的所有属性 */
+(NSArray *)getAllProperties
{
u_int count;
// 传递count的地址过去 &count
objc_property_t *properties =class_copyPropertyList([self class], &count);
//arrayWithCapacity的效率稍微高那么一丢丢
NSMutableArray *propertiesArray = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count ; i++)
{
//此刻得到的propertyName为c语言的字符串
const char* propertyName =property_getName(properties[i]);
//此步骤把c语言的字符串转换为OC的NSString
[propertiesArray addObject: [NSString stringWithUTF8String: propertyName]];
}
//class_copyPropertyList底层为C语言,所以我们一定要记得释放properties
// You must free the array with free().
free(properties);
return propertiesArray;
}
/* 获取对象的所有方法 */
+(NSArray *)getAllMethods
{
unsigned int methodCount =0;
Method* methodList = class_copyMethodList([self class],&methodCount);
NSMutableArray *methodsArray = [NSMutableArray arrayWithCapacity:methodCount];
for(int i=0;i<methodCount;i++)
{
Method temp = methodList[i];
IMP imp = method_getImplementation(temp);
SEL name_f = method_getName(temp);
const char* name_s =sel_getName(method_getName(temp));
int arguments = method_getNumberOfArguments(temp);
const char* encoding =method_getTypeEncoding(temp);
NSLog(@"方法名:%@,参数个数:%d,编码方式:%@",[NSString stringWithUTF8String:name_s],
arguments,
[NSString stringWithUTF8String:encoding]);
[methodsArray addObject:[NSString stringWithUTF8String:name_s]];
}
free(methodList);
return methodsArray;
}
/* 获取对象的所有属性和属性内容 */
+ (NSDictionary *)getAllPropertiesAndVaules
{
NSMutableDictionary *propsDic = [NSMutableDictionary dictionary];
unsigned int outCount;
objc_property_t *properties =class_copyPropertyList([self class], &outCount);
for ( int i = 0; i<outCount; i++)
{
objc_property_t property = properties[i];
const char* char_f =property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:char_f];
id propertyValue = [self valueForKey:(NSString *)propertyName];
if (propertyValue) {
[propsDic setObject:propertyValue forKey:propertyName];
}
}
free(properties);
return propsDic;
}
@end
调用时:
包含头文件
#import "NSObject+JGRuntime.h"
直接调用
如我在一个控制器的导航栏按钮点击时调用时
JGLog(@"\n%@",[JGWorkLogViewController getAllMethods]);
打印结果是:
(
setupChildVces,
setupTitlesView,
setupContentView,
titleClick:,
setTitlesView:,
setIndicatorView:,
setSelectedButton:,
indicatorView,
selectedButton,
titlesView,
setNavItem,
rightItemBtnClick,
leftitemBtnClick,
loadCtrlWithLogTypeStr:,
setContentView:,
scrollViewDidEndDecelerating:,
scrollViewDidEndScrollingAnimation:,
didReceiveMemoryWarning,
viewDidLoad,
.cxx_destruct,
contentView,
)