Swizzling:偷梁换柱的黑魔法!

Swizzling:偷梁换柱的黑魔法!

我们知道,OC是一门动态运行时语言。我们也知道,OC中的函数调用本质上其实是消息的发送:objc_MsgSend(someObject, @selector(methodName), parameters)所有要调用的函数,编译阶段是无法确定的,只有到运行的时候才能确定!正因为有此特性,所以在运行阶段,我们都还可以做很多事,而要把本来应该实现的方法A,偷偷换成方法B,便是其中的一种,这种技术叫做:Method Swizzling(方法交换)!

具体相关的概念就不再啰嗦了,网上都有很多了,可以自行google或者查阅《Effective Objective-C 2.0 编写高质量iOS与OS X 代码的52个有效方法》的第13条,介绍的都比较详细了。这里就总结一下相关的应用!

调试用

假如每次调用NSString的lowerCaseString方法时,不要每次都去NSLog,希望直接调用系统的方法时每次都可以输出log,那么这时候就可以用到该技术:

@interface NSString (XPPMyAdditions)

- (NSString *)xpp_myLowerCaseString;

@end

@implementation NSString (XPPMyAdditions)

- (NSString *)xpp_myLowerCaseString
{
    NSString *LowerString = [self xpp_myLowerCaseString];
    NSLog(@"%@->%@", self, LowerString);
    return LowerString;
}

接下来做的就是把这个分类里面的方法和原生的方法交换一下:

void swizzling(){
    Method originalMtd = class_getInstanceMethod([UIF class], @selector(xpp_myLowerCaseString));
    Method swappedMtd = class_getInstanceMethod([NSString class], @selector(lowercaseString));
    method_exchangeImplementations(originalMtd, swappedMtd);

}

那么在以后,直接调用系统原生的lowercaseString方法时,实际上调用的是分类里面的方法,在达到原来目的的同时,还能输出结果,非常方便!

注意:交换过后调用NSString原生的lowerCaseString实际上是调用xpp_myLowerCaseString;而在现在的xpp_myLowerCaseString里面,其实[self xpp_myLowerCaseString]实际上是调用了系统的lowerCaseString方法达到把字符串变为小写的目的。所以,不会陷入死循环!

一次性更改

假如今天你接到产品的需求,把App里面所有的字体减小两个点。你怎么办?搜索找工程里面的systemFontOfSize:方法,挨个把字号-2;好,没问题,可以。那第二天她觉得这个字太小了,再加1个点吧^ _ ^。
这时候,方法交换技术派上用成了:

@interface UIFont (XppMyAdditions)

+ (UIFont *)xpp_systemFontOfSize:(CGFloat)size;

@end

@implementation UIFont (XppMyAdditions)

+ (UIFont *)xpp_systemFontOfSize:(CGFloat)size
{
    UIFont *font = [self xpp_systemFontOfSize:(size-2)];
    NSLog(@"%f---->%f",size, font.pointSize);
    return font;
}

接下来,再把系统的方法和该方法交换一下:

    Method m1 = class_getClassMethod([UIFont class], @selector(systemFontOfSize:));
    Method m2 = class_getClassMethod([UIFont class], @selector(xpp_systemFontOfSize:));
    method_exchangeImplementations(m1, m2);

注意:这里是类方法!不是实例方法,所以注意API的调用和分类方法要匹配,否则不会报错,但是你会发现没效果

诶,这时候就太方便了,随便你想加2个点还是减1个点,无所谓,一个数字的事儿。

所以,从上看出,方法交换技术还是作用挺大的。只是尽量还是少用,一般就用来调试或者做些需要大量改动的处理。一般代码中不要为了show技术胡乱使用,这样会导致代码结构太差,用的多了,代码可读性也变差了,所以尽量还是少用,要不然哪天出bug了你都不知道问题在哪儿。合理使用即可!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值