iOS运行时与method swizzling
2016-04-26 18:24
337 查看
http://blog.csdn.net/sakulafly/article/details/27575871
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
[objc] view
plain copy
@interface NSString (wzTest)
- (NSString*)myLowerString;
@end
@implementation NSString (wzTest)
- (NSString*)myLowerString
{
NSString *lowerString = [self myLowerString];
NSLog(@"%@ => %@", self, lowerString);
return lowerString;
}
@end
这里有一个地方解释一下,在myLowerString方法里面,看起来递归调用了自身。但是,我们会用原来的lowercaseString方法去替换自己写的myLowerString方法,所以这里并没有调用自身,而是调用了原来的lowercaseString方法。这点请注意一下。
其次替换系统原来的lowercaseString方法,使用runtime里面的方法。
[objc] view
plain copy
Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
Method swapMethod = class_getInstanceMethod([NSString class], @selector(myLowerString));
method_exchangeImplementations(originalMethod, swapMethod);
NSString *testStr = @"thIs is THE Test STRING";
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就可以正常的工作。
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
[objc] view
plain copy
@interface NSString (wzTest)
- (NSString*)myLowerString;
@end
@implementation NSString (wzTest)
- (NSString*)myLowerString
{
NSString *lowerString = [self myLowerString];
NSLog(@"%@ => %@", self, lowerString);
return lowerString;
}
@end
这里有一个地方解释一下,在myLowerString方法里面,看起来递归调用了自身。但是,我们会用原来的lowercaseString方法去替换自己写的myLowerString方法,所以这里并没有调用自身,而是调用了原来的lowercaseString方法。这点请注意一下。
其次替换系统原来的lowercaseString方法,使用runtime里面的方法。
[objc] view
plain copy
Method originalMethod = class_getInstanceMethod([NSString class], @selector(lowercaseString));
Method swapMethod = class_getInstanceMethod([NSString class], @selector(myLowerString));
method_exchangeImplementations(originalMethod, swapMethod);
NSString *testStr = @"thIs is THE Test STRING";
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
- [ios]CGContext 函数说明
- [ios]presentModalViewController和dismissModalViewControllerAnimated汇总
- iOS-正则表达式的使用
- iOS--串口通讯初始化
- 【转载】Xcode 4.1~4.6 + iOS 5、iOS 6免证书(iDP)开发+真机调试+生成IPA全攻略
- 如何让iOS应用程序访问到 dev下的设备
- ios6.0横竖屏切换问题解决
- 2011年冬季最新斯坦福大学公开课:iOS程序开发教程【中文字幕】
- ios和配件进行通讯[转]
- ios开发 获取系统时间
- iOS 常用代码汇总(持续更新)
- iOS开发实例-七杯茶奶茶点餐系统
- iOS 编译百度地图静态库-合二为一
- iOS-coverFlow效果简单实现
- iOS home键直接退出
- iOS单例模式使用
- 截取部分图片并显示-ios例子[转载]
- 关于IOS获取本地通讯录信息(包含iOS9.0前后)
- 一步一步构建iOS持续集成:Jenkins+GitLab+蒲公英+FTP