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

在Objective-C中有个@selector,在很多地方被翻译成“选择子”。实际上,对于类的实例对象来说,类的方法是用一个数字来代表的,并非
是我们看到的一个长长的带着:这个字符的一串字符串。通过这个@selector就可以把这个方法的名字转成所对应的数字。当一个类确定后,实际上每个方
法的@selector的值就是固定的,说到这里,你一定可以想到method
swizzling是什么一个东东了,没错,如果我们原来有个A方法,@selector(A)就是一个数字,我们的对象在接收到一个消息后就去查找对应
的方法并运行——如果,我们把@selector(B)的数字换成了原来@selector(A)的数字,那么此时对象虽然受到A消息,但会去运行B方
法!

在iOS中,这是完全可以实现的,那么我们什么时候会需要这么做呢?我觉得有2个时候:

1. 破解,毋庸讳言,这绝对是破解的利器,不解释了。

2. 在开发调试过程中,如果你对某个库里的方法不确定或者觉得需要扩展的时候,你可以自己写一个去代替它。因为Objective-C是有Category的,所以扩展功能没啥必要,但调试时增加一些打印语句是很方便实际的。

举个例子,NSString里面的lowercaseString方法,如果我不太清楚这个方法都干了什么,我就可以自己写个方法来替换它,这个方法里面增加打印语句,这样log里面就一目了然了。

首先需要增加一个NSString的Category

  1. @interface NSString (wzTest)
  2. - (NSString*)myLowerString;
  3. @end
  4. @implementation NSString (wzTest)
  5. - (NSString*)myLowerString
  6. {
  7. NSString *lowerString = [self myLowerString];
  8. NSLog(@"%@ => %@", self, lowerString);
  9. return  lowerString;
  10. }
  11. @end

这里有一个地方解释一下,在myLowerString方法里面,看起来递归调用了自身。但是,我们会用原来的lowercaseString方法去替换自己写的myLowerString方法,所以这里并没有调用自身,而是调用了原来的lowercaseString方法。这点请注意一下。

其次替换系统原来的lowercaseString方法,使用runtime里面的方法。

  1. Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
  2. Method swapMethod = class_getInstanceMethod([NSString class], @selector(myLowerString));
  3. method_exchangeImplementations(originalMethod, swapMethod);
  4. NSString *testStr = @"thIs is THE Test STRING";
  5. NSLog(@"lowerString of testStr=%@", [testStr lowercaseString]);

我们来看一下log的结果:

2014-05-29 22:17:55.514 testTableView[1582:a0b] thIs is THE Test STRING => this is the test string

2014-05-29 22:17:55.514 testTableView[1582:a0b] lowerString of testStr=this is the test string

我们可以看到,系统中使用是继续使用lowercaseString方法的,不过实际执行的是我们新增的方法。当你不需要这样做的时候,关闭method swizzling方法就可以恢复了。

我们的例子中是增加了打印语句,实际上还可以做更多地操作。这在用第三方库调试的时候是非常有用的一个方法,可以很方便的查看变量的内容或做一些其他工作。调试结束后,关闭method swizzling就可以正常的工作。

iOS运行时与method swizzling的更多相关文章

  1. iOS执行时与method swizzling

    C语言是静态语言,它的工作方式是通过函数调用,这样在编译时我们就已经确定程序怎样执行的.而Objective-C是动态语言,它并不是通过调用类的方法来执行功能,而是给对象发送消息,对象在接收到消息之后 ...

  2. 【原】iOS动态性(三) Method Swizzling以及AOP编程:在运行时进行代码注入

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  3. IOS 开发之 Method Swizzling + Category

    ios 分类中如果增加的方法与被扩展的类方法名重复,则原方法就没法被调用….看以下例子 例如: @interface ClassA : NSObject - (NSString *) myMethod ...

  4. IOS 开发之 Method Swizzling

    ios 分类中如果增加的方法与被扩展的类方法名重复,则原方法就没法被调用….看以下例子 例如: @interface ClassA : NSObject - (NSString *) myMethod ...

  5. Method Swizzling

    学习博客: http://www.cocoachina.com/ios/20160121/15076.html (这个作者太牛了,写了我一直想知道的类簇的swizz方法) 一. 一般的swizz 先给 ...

  6. Objective-C运行时编程 - 方法混写 Method Swizzling

    摘要: 本文描述方法混写对实例.类.父类.不存在的方法等情况处理,属于Objective-C(oc)运行时(runtime)编程范围. 编程环境:Xcode 6.1.1, Yosemite,iOS 8 ...

  7. OBJC运行时方法替换(Method swizzling)

    在上周associated objects一文中,我们开始探索Objective-C运行时的一些黑魔法.本周我们继续前行,来讨论可能是最受争议的运行时技术:method swizzling.   Me ...

  8. Method Swizzling以及AOP编程:在运行时进行代码注入-备用

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  9. iOS 使用Method Swizzling隐藏Status Bar

    在iOS 6中,隐藏Status Bar很的简单. // iOS 6及曾经,隐藏状态栏 [[UIApplication sharedApplication] setStatusBarHidden:YE ...

随机推荐

  1. JAVA线程同步辅助类CyclicBarrier循环屏障

    CyclicBarrier是一个同步辅助类,主要作用是让一组线程互相等待,知道都到达一个公共障点,在一起走.在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrie ...

  2. javascript 面向对象(转)

    1.使用[]调用对象的属性和方法 function User() { this.age = 21; this.sex = "男?"; } var user = new User() ...

  3. Bootstrap_分页

    一.带页码的分页导航 <ul class="pagination"> <li><a href="#">«</a> ...

  4. angular之控制器(0)

    一.控制器的含义 在angularJS中,controlle是一个javascript函数/类,用于操作作用域中,各个对象的初始状态以及相应的行为 二.控制器的作用 1. 控制 AngularJS 应 ...

  5. DSO、CUBE区别(覆盖、合计)

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  6. 【springMVC】简单的前后端数据交流

    最最常见两种,一则返回视图模板(文档),二则为json数据.就使用一个源代码文件来看看springmvc是怎么做到的. 1.UserController.java源代码文件 (这里额外的使用了fast ...

  7. mysql 日期格式化

    SELECT plc.id, plc.policy_no, plc.out_date, og.organ_name, ir.insurer_name, pd.product_name, plc.pol ...

  8. javascript 去掉空格之后的字符 正则表达式

    从后端数据库读取时间时,经常会把整个日期年月日包括时分秒都取到,如2015-1-28 14:56:00,但是一般的我们只需要前面的年月日就行了.一个简单的方法,直接用split(" &quo ...

  9. 页面加载后resize页面布局

    在我们写web的时候,有的时候页面加载完以后,布局位置有一些问题,手动改变窗口大小后则正常显示位置. 其实,我们手动改变窗口大小,是执行了resize方法. share一下兼容方法: coffee c ...

  10. nginx 负载均衡策略

    nginx 负载均衡策略   1. 轮询轮询方式是nginx负载均衡的默认策略,根据每个server的权重值来轮流发送请求,例如:upstream backend {server backend1.e ...