美文网首页
IOS运行时Method Swizzling (1)

IOS运行时Method Swizzling (1)

作者: SHUTUP | 来源:发表于2016-03-02 21:35 被阅读95次

    前言

    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]在运行时为类添加方法

    相关文章

      网友评论

          本文标题:IOS运行时Method Swizzling (1)

          本文链接:https://www.haomeiwen.com/subject/flvnkttx.html