Runtime编程 - Swizzle Stuff

objective-c的instance method调用实际上是查表再通过C形式调用的过程,这个函数表是可以操作的,这样就给了我们可以在运行时修改的机会,这种做法叫swizzle .

<objc/runtime.h>里面提供了API,我们以调换NSString的lowercaseString与我们的category里面的stoneLowercaseString为目标。实现swizzle基本上会用到category,先看category里面的代码:

.h文件
===================================
#import <Foundation/Foundation.h>

@interface NSString (Stone)
- (
NSString *)stoneLowercaseString;
@end

.m文件
===================================
#import "NSString+Stone.h"

@implementation NSString (Stone)
- (
NSString *)stoneLowercaseString{
   
// 递归调用?不是,实际上在运行到这里之前我们已经做了 swap ,所以这里
   
// 调用的是原版的 lowercaseString ,达到了调用原方法的目的。
   
NSString *lowercase = [ self stoneLowercaseString ];
   
NSLog ( @"[Stone] %@" , lowercase);
   
return lowercase;
}
@end


方法的swap以及测试,swizzle的调用时机越早越好,一般会写在app的didLaunch事件中。
===================================
    // swizzle stuff
   
// 这里注意不要写成了 class_getClassMethod
   
Method originalMethod = class_getInstanceMethod ([ NSString class ], @selector (lowercaseString));
   
Method stoneMethod = class_getInstanceMethod ([ NSString class ], @selector (stoneLowercaseString));
   
method_exchangeImplementations (originalMethod, stoneMethod);
   
   
// test
   
NSString *test = @"Gundam Exia" ;
    NSLog(@"lower = %@", [test lowercaseString]);


输出
===================================
2015-09-08 09:59:08.621 SwizzleDemo[16503:811706] [Stone] gundam exia
2015-09-08 09:59:08.622 SwizzleDemo[16503:811706] lower = gundam exia


*注意点
不要为了用swizzle而用swizzle,此技巧一旦出现问题的话会非常难以调试和debug。因此,除非是常规办法没法实现或者实现起来很麻烦的需求,一般避免用swizzle。最常见的用法是用于调试没有源码的类实现等等。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值