iOS面试题+基础知识runtime

iOS 方法交换(methodSwizzling)

2017-11-24  本文已影响155人  uniapp

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交换实现方式。

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

上一篇 下一篇

猜你喜欢

热点阅读