您的位置:首页 > 移动开发 > IOS开发

Method swizzling

2016-06-22 17:13 302 查看
“函数替换”这个网上很多很多的教程了,可以自行搜索,贴上比较好的教程:
http://www.cocoachina.com/industry/20140225/7880.html
利用一些技巧:

例如,调用的时候也可以用runtime的objc_msgSend来发消息。

可以在NSObject类方法的 load 或者 initialize 方法加GCD的单次执行来只实现一次

有时候会遇到Swizzling失效的坑爹情况,除了基本的语法出错,还要注意一点,如下:

Class class = [self class];

NSLog(@"Hooked with ReYunChannel Class : %@", NSStringFromClass(class));

SEL originalSelector = @selector(initWithappKey:withChannelId:);
SEL swizzledSelector = @selector(swizzledInitWithAppId:channelID:);

Method originalMethod = class_getClassMethod(class, originalSelector);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

BOOL didAddMethod =
class_addMethod(class, originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));

if (didAddMethod) {
class_replaceMethod(class, swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}


这一段代码是NSHipster的标准例子,但是有时候会调用失效,看看这个大哥怎么调用的: https://spin.atomicobject.com/2014/12/30/method-swizzling-objective-c/
很明显,直接交换实现,就可以解决了,如下:

Class class = [self class];

NSLog(@"Hooked with ReYunChannel Class : %@", NSStringFromClass(class));

SEL originalSelector = @selector(initWithappKey:withChannelId:);
SEL swizzledSelector = @selector(swizzledInitWithAppId:channelID:);

Method originalMethod = class_getClassMethod(class, originalSelector);
Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

BOOL didAddMethod =
class_addMethod(class, originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));

if (didAddMethod) {
method_exchangeImplementations(originalMethod, swizzledMethod);

}


还有一些好的文章可以看看:
https://blog.newrelic.com/2014/04/16/right-way-to-swizzle/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  iOS