【Effective Objective-C 2.0 读书笔记】第十三条:用“方法调配技术“调试”黑盒方法“

第十三条:用“方法调配技术“调试”黑盒方法“

在消息解析时,与给定的选择子名称相对应的方法是不是也可以在运行时改变呢?

没错,就是这样。

若能善用此特性,则可发挥出巨大优势,因为我们既不需要源代码,也不需要通过继承子类来覆写方法就能改变这个类本身的功能。

这样一来,新功能将在本类的所有实例中生效,而不是仅限于覆写了相关方法的那些子类实例。

此方案经常成为“方法调配”(method swizzling)。

类的方法列表会把选择子的名称映射到相关的方法实现之上,使得“动态消息派发系统”能够据此找到应该调用的方法。

这些方法均以函数指针的形式来表示,这种指针叫做IMP,其原型如下:

id (* IMP) (id, SEL, ….)

类中的方法通过映射表把每个选择子都映射到不同的IMP上。

Objective-C运行期系统提供的几个方法都能够用来操作这张表。

开发者可以向其中增加选择子,也可以改变某选择子所对应的方法实现。

还可以交换两个选择子所映射到的指针。

无须修改类,或者编写子类,只要修改了“方法表”的布局,就会反映到程序中所有的实例上。

想交换方法实现,可用下列函数:

void method_exchangeImplementations(Method m1, Method m2)

此函数的两个参数表示待交换的两个方法实现,而方法实现则可以通过下列函数获得:

Method class_getInstanceMethod(Class aClass, SEL aSelector)

此函数根据给定的选择子从类中取出与之相关的方法。

例如:

Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));

Method swappedMethod = class_getInstanceMethod([NSString class], @selector(uppercaseString));

method_exchangeImplemetations(originalMethod, swappedMethod);

然而在实际应用中,像这样直接交换两个方法的实现的,意义并不大。

通常,我们新编写一个方法,在此方法中实现所需要的附加功能,与原有的方法交换。并调用原有实现。

通过此方法,开发者可以为那些“完全不知道其具体实现的”黑盒方法增加日志记录功能,这非常有利于程序的调试。

不能因为Objective-C有这个特性就一定要用它。若是滥用,反而会令代码变得不易读懂且难于维护。

【要点】

在运行期,可以向类中新增或替换选择子所对应的方法实现。

使用另一份实现来替换原有的方法实现,这道工序叫做“方法调配”,开发者通常用此技术向原有视线中添加新功能。

一般来说,只有调试程序的时候才需要在运行期修改方法实现,这种做法不宜滥用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,860评论 0 9
  • 我们常常会听说 Objective-C 是一门动态语言,那么这个「动态」表现在哪呢?我想最主要的表现就是 Obje...
    Ethan_Struggle阅读 6,595评论 0 7
  • 转载:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麦子阅读 4,112评论 0 2
  • 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的...
    lylaut阅读 4,221评论 0 4
  • 文中的实验代码我放在了这个项目中。 以下内容是我通过整理[这篇博客] (http://yulingtianxia....
    茗涙阅读 4,468评论 0 6