IOS运行时Method Swizzling (1)

2016-03-02  本文已影响95人  SHUTUP

前言

C语言是静态语言,它的工作方式是通过函数调用,这样在编译时我们就已经确定程序如何运行的。而Objective-C是动态语言,它并非通过调用类的方法来执行功能,而是给对象发送消息,对象在接收到消息之后会去找匹配的方法来运行。这种做法就把C语言在编译时的工作挪到了运行时来做,可以获得额外的灵活性。
简单理解呢,就是你调用一个方法,但它最终调用的实现是可以改变的,而且你可以在运行时给类添加方法。

添加类不存在的方法

下面的代码定义了两个按钮的响应事件,如果直接点击第一个按钮,那么程序会奔溃,报错提示找不到方法,而如果先点击第二个按钮,那么再点击第一个按钮也不好奔溃了,相反sayHello函数得到了调用。

void sayHello(id self, SEL _cmd)
{
    NSLog(@"hello !");
}
- (IBAction)btnClicked:(id)sender {
    [self performSelector:@selector(sayHello2)];
}
- (IBAction)swizzlingBtnClicked:(id)sender {
    class_addMethod([self class], @selector(sayHello2), (IMP)sayHello, "v@:");
}

这里提一句,Obj-C的方法 (method)就是一个至少需要两个参数(self,_cmd)的C函数,这个函数仅仅输出一句Hello。接下来在addMethod方法中,我们调 用class_addMethod()为类添加方法,class_addMethod()是这样定义的:

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
参数说明:
cls:被添加方法的类
name:可以理解为方法名,这个貌似随便起名,比如我们这里叫sayHello2
imp:实现这个方法的函数
types:一个定义该函数返回值类型和参数类型的字符串

下面举一个例子来讲一下上面的types

int say(id self, SEL _cmd, NSString *str) {     
NSLog(@"%@", str);    
 return 100;//随便返回个值 
}

class_addMethod这句就应该这么写:
1

class_addMethod([EmptyClass class], @selector(say:), (IMP)say, "i@:@");

其中types参数为"i@:@“,按顺序分别表示:
i:返回值类型int,若是v则表示void
@:参数id(self)
::SEL(_cmd)
@:id(str)

demo

稍等

参考

[iOS]在运行时为类添加方法

上一篇下一篇

猜你喜欢

热点阅读