美文网首页
iOS Runtime修炼<四>

iOS Runtime修炼<四>

作者: 莮亾 | 来源:发表于2017-02-08 17:49 被阅读22次

裸露在我的面前

通过这段时间的接触,我与Runtime都觉得与彼此很合得来,于是它打算将所有的招式都展现给我。本来我就是武学奇才,再加上天资聪慧,不一会儿,我就领悟了许多。当然,我也会共享我的一些好东西给它,毕竟礼尚往来嘛。


BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

这一招式之前简单的接触过,作用就是为某个类增加一个新的方法。如果类中已经存在叫这个名字的方法,函数就会返回NO。需要注意的地方是如果添加的方法覆盖了父类中的实现(这个是可以的),那么这个方法不会在当前类中生效,也就是说方法仍然是父类中的实现。要想改变这种局面,可以使用method_exchangeImplementations函数交换两个方法的实现。如:

void method_exchangeImplementations(Method m1, Method m2) {
    // 大概的实现
    IMP imp1 = method_getImplementation(m1);
    IMP imp2 = method_getImplementation(m2);
    method_setImplementation(m1, imp2);
    method_setImplementation(m2, imp1); 
}

在此顺便说一下types参数的心法:如之前传入的“v@:”三个字符,第一个代表返回值,没有返回值,则是v;第二个跟第三个字符是固定的,因为每个方法都有固定的2个参数(self和_cmd);@代表对象,: 代表方法选择器。更多的字符含义请参考 (Objective-C Runtime Programming Guide > Type Encodings)。

Method class_getInstanceMethod(Class aClass, SEL aSelector)

这一招式是从参数aClass中得到选择器为aSelector的实例方法;若指定的类与其父类中都不包含指定的选择器,则返回NULL。

通过class_getInstanceMethod我们就能顺利的使用method_exchangeImplementations函数了。只有在较少情况下使用method_exchangeImplementations函数,如下是给黑盒方法增加日志记录的例子:
NSString有一个lowercaseString方法,我们可以为其添加日记,记录转换的过程。

@interface NSString (LJAddLog) 
- (NSString *)lj_logLowercaseString;
@end

@implementation NSString (LJAddLog)
- (NSString *) lj_logLowercaseString {
    /*不会陷入无限循环,因为在运行期,此方法是指向lowercaseString方法的,相当于是在调用lowercaseString方法*/
    NSString *low = [self lj_logLowercaseString];
    /*打印加入的日志记录*/
    NSLog(@"%@ ---> %@", self, low);
    /*返回转换后的小写字母字符串*/
    return low;
}

Method originMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
Method addLogMethod = class_getInstanceMethod([NSString class], @selector(lj_logLowercaseString));
method_exchangeImplementations(originMethod, addLogMethod);

NSString *s = @"XIE MO TUI SAN";
/*在运行期调用的是lj_logLowercaseString方法*/
NSString *lowString = [s lowercaseString];
// XIE MO TUI SAN ---> xie mo tui san

相类似的招式还有class_getClassMethod,这里就不再说了。

Method * class_copyMethodList(Class cls, unsigned int *outCount)

这一招式是用来得到参数cls中的方法列表,输出有两个,outCount和Method *(指针数组)。返回的指针数组内存需要调用者管理。
⚠️此方法不会获取父类中的方法,这是与class_getInstanceMethod最大的区别。

IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)

这一招式有点意思,它的作用是替换某个类中的某个方法,参数就不用再说了,太简单。然而此招式有过人之处,那就是如果类中没有被替换的方法,则会自动调用class_addMethod将方法增加到类中;否则就使用method_setImplementation将方法替换。返回值是被替换前的方法的实现地址。

没想到这厮有这么多招式,还好彼此之间有那么些许相似,不然我就要跟它混记一辈子了。我也跟它讲了我的经历,当它听到我要离开的消息,有点不舍的感觉,但毕竟男儿志在四方,它也便理解了,于是给我介绍了一位它的朋友,说是让我去找它,能助我早日修仙成功。


关注微信公众号CodingArtist,可以第一时间得到文章更新通知! _

相关文章

  • iOS Runtime修炼<四>

    裸露在我的面前 通过这段时间的接触,我与Runtime都觉得与彼此很合得来,于是它打算将所有的招式都展现给我。本来...

  • iOS Runtime修炼<二>

    基情四射的日子 我总是对神秘的事物产生兴趣,自从知道了Objective-C的Runtime技能,我便试着接近它,...

  • iOS Runtime修炼<一>

    初来乍到 由于触犯天条,被打落凡间,记忆全无,唯独iOS三个字总是被我不经意间提起。 也许冥冥之中自有安排,一个偶...

  • iOS Runtime修炼<三>

    修仙的道路不需要敌人 Runtime渐渐清醒过来,毕竟两瓶啤酒,没有多大劲,它怀疑的眼光看的我很不自在。我说:“大...

  • Mybatis中特殊符号转移

    1. 写法1 原符号替换符号<<<=<=>>>=>=<><>&&'&a...

  • test

    <script>alert(1);</script>

  • 无标题文章

    <script>alert('hello’);</script>

  • Mybatis 中大于等于小于等于的写法

    第一种写法:原符号 < <= > >= & ' "替换符号 < <= > >= &a...

  • MyBatis大于小于转义

    说明小于小于等于大于大于等于&'''原符号<<=>>=&'"替换符号<<=>>=&...

  • iOS源码解析:runtime<四> runtime

    runtime的API有很多,内容很丰富,下面按照类方法,成员变量相关方法,属性相关方法,方法相关等进行说明。 R...

网友评论

      本文标题:iOS Runtime修炼<四>

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