iOS 方法交换(methodSwizzling)

iOS运行中runtime中采用消息分发机制,允许开发者对其进行方法交换,替换某个类的方法实现或者在执行方法前添加自定义内容,控制App的执行流程。实现方式可以参考如下两篇:
Runtime Method Swizzling 开发实例汇总(持续更新中)
iOS中的黑魔法:Method Swizzling
下面方法交换中令人迷惑的if/else进行详细解释:

+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Method originalMethod = class_getInstanceMethod([self class], @selector(originalMethod));
        Method swizzlingMethod = class_getInstanceMethod([self class], @selector(swizzlingMethod));
        BOOL isAdded = class_addMethod([self class], method_getName(originalMethod), method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
//添加不存在的方法,返回Yes;
//        Method originalMethodTest = class_getInstanceMethod([self class], @selector(originalMethodTest));
//        BOOL isAddedTest = class_addMethod([self class], method_getName(originalMethodTest), method_getImplementation(originalMethodTest), method_getTypeEncoding(originalMethod));
        if (isAdded)
        {
            NSLog(@"方法在原类中不存在,已经添加成功,用下面的方法替换其实现");
            class_replaceMethod([self class], method_getName(originalMethod), method_getImplementation(swizzlingMethod), method_getTypeEncoding(swizzlingMethod));
        }
        else
        {
            NSLog(@"方法在原类中存在,用下面的方法交换其实现方法");
            method_exchangeImplementations(originalMethod, swizzlingMethod);
        }
        
        NSLog(@"end");
    });
    
}
- (void)originalMethod{
    NSLog(@"原类中的方法");
}


- (void)swizzlingMethod{
    NSLog(@"替换过的方法");
}

先明确以下知识点:
ObjectClass中方法的区分基于方法名称name和有无参数variable区分方法是否一样。

//1
- (void)originalMethod{
    NSLog(@"原类中的方法");
}
//2
- (void)originalMethod:(NSString *)name{
    NSLog(@"原类中的方法");
}
//3
- (void)originalMethod:(int)count{
    NSLog(@"原类中的方法");
}

1和2是不同的方法,2和3是同一个方法;

文档中对class_addMethod的解释如下:

 * @return YES if the method was added successfully, otherwise NO 
 *  (for example, the class already contains a method implementation with that name).
 *
 * @note class_addMethod will add an override of a superclass's implementation, 
 *  but will not replace an existing implementation in this class. 
 *  To change an existing implementation, use method_setImplementation.
 */
OBJC_EXPORT BOOL
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, 
                const char * _Nullable types) 

添加成功返回Yes,否则返回No。也就是说用class_addMethod添加类中不存在的方法(方法名或者参数不一致)时,返回Yes。然后可以用class_replaceMethod方法替换实现方式,如果放回No表明原类中已经定义了方法实现,需要调用method_exchangeImplementations交换实现方式。

喜欢和关注都是对我的鼓励和支持~

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 2,271评论 0赞 9
  • 本文转载自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex阅读 956评论 0赞 1
  • 转载:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麦子阅读 894评论 0赞 2
  • 本文详细整理了 Cocoa 的 Runtime 系统的知识,它使得 Objective-C 如虎添翼,具备了灵活的...
    lylaut阅读 909评论 0赞 4
  • 【知-学习】 1.朗读0分钟。 2.《六项精进》大纲诵读0遍。 【经典名句分享】 世界上那些了不起的成就,大多是耐...
    玉_莲子阅读 133评论 0赞 0

友情链接更多精彩内容