五、让我看看你的方法吧
变量通过runtime机制我们可以取到和改变值,那么我们再大胆一点,试试那些私有的方法,首先我们在MyObject类中添加一些方法,我们只实现,并不声明他们:
@interface MyObject()
{
@private
NSString * privateThree;
}
@end
@implementation MyObject
- (instancetype)init
{
self = [super init];
if (self) {
privateOne=1;
privateTow=@"Tow";
privateThree=@"Three";
}
return self;
}
-(NSString *)description{
return [NSString stringWithFormat:@"one=%d\ntow=%@\nthree=%@\n",privateOne,privateTow,privateThree];
}
-(NSString *)method1{
return @"method1";
}
-(NSString *)method2{
return @"method2";
}
这样的方法我们在外面是无法调用他们的,和操作变量的思路一样,我们先要捕获这些方法:
//获取所有成员方法
Method * mem = class_copyMethodList([MyObject class], &count);
//遍历
for(int i=0;i<count;i++){
SEL name = method_getName(mem[i]);
NSString * method = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
NSLog(@"%@\n",method);
}
打印如下:
得到了这些方法名,我们大胆的调用即可:
MyObject * obj = [[MyObject alloc]init];
NSLog(@"%@",[obj method1]);
Tip:这里编译器不会给我们方法提示,放心大胆的调用即可。
六、动态的为类添加方法
这个runtime机制最强大的部分要到了,试想,如果我们可以动态的向类中添加方法,那将是一件多么令人激动的事情,注意,这里是动态的添加,和类别的最大不同在于这种方式是运行时才决定是否添加方法的。
- (void)viewDidLoad {
[super viewDidLoad];
//添加一个新的方法,第三个参数是返回值的类型v是void,i是int,:是SEL,对象是@等
class_addMethod([MyObject class], @selector(method3), (IMP)logHAHA, "v");
unsigned int count = 0;
Method * mem = class_copyMethodList([MyObject class], &count);
for(int i=0;i<count;i++){
SEL name = method_getName(mem[i]);
NSString * method = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
NSLog(@"%@\n",method);
}
MyObject * obj = [[MyObject alloc]init];
//运行这个方法
[obj performSelector:@selector(method3)];
}
//方法的实现
void logHAHA(){
NSLog(@"HAHA");
}
运行结果如下:
从前五行可以看出,方法已经加进去了,从最后一行可以看出,执行没有问题。
七、做点小手脚
程序员总是得寸进尺的,现在,我们要做点事情,用我们的函数替换掉类中的函数:
- (void)viewDidLoad {
[super viewDidLoad];
MyObject * obj = [[MyObject alloc]init];
//替换之前的方法
NSLog(@"%@", [obj method1]);
//替换
class_replaceMethod([MyObject class], @selector(method1), (IMP)logHAHA, "v");
[obj method1];
}
void logHAHA(){
NSLog(@"HAHA");
}
打印如下:
这次够cool吧,通过这个方法,我们可以把系统的函数都搞乱套。当然,runtime还有许多很cool的方法:
id object_copy(id obj, size_t size)
拷贝一个对象
id object_dispose(id obj)
释放一个对象
const char *object_getClassName(id obj)
获取对象的类名
ive
void method_exchangeImplementations(Method m1, Method m2)
交换两个方法的实现