iOS面试题/2019ios学习

iOS底层原理 16 :底层面试题

2020-10-23  本文已影响0人  smooth_lgh
1. 主类的方法和分类的方法重名,会如何调用?
2.方法的本质?sel是什么?imp是什么?两者之间的关系又是什么?


3. Runtime是如何实现weak,为什么可以自动置为nil?
4.Associate方法关联的属性,需要手动在delloc里面释放吗?

不需要 ,应为在dealloc的实现里面已经实现
dealloc ->_objc_rootDealloc(self)->obj->rootDealloc()->object_dispose()->objc_destructInstance()



5.Method Swizzling的坑与应用
  1. 首先Method Swizzling方法最好是能够放在+load或+initialize方法里面,保证第一次发送消息之前就已经执行了方法切换的代码
  2. method_exchangeImplementations()方法交换的本质: 交换imp(即方法的实现)
  3. 为避免Method Swizzling出现的各种坑,设计了一下实现代码:
@interface LGRuntimeTool : NSObject
/**
 交换方法
 @param cls 交换对象
 @param oriSEL 原始方法编号
 @param swizzledSEL 交换的方法编号
 */
+ (void)lg_bestMethodSwizzlingWithClass:(Class)cls oriSEL:(SEL)oriSEL swizzledSEL:(SEL)swizzledSEL;

@end
@implementation LGRuntimeTool
+ (void)lg_bestMethodSwizzlingWithClass:(Class)cls oriSEL:(SEL)oriSEL swizzledSEL:(SEL)swizzledSEL{
    
    if (!cls) NSLog(@"传入的交换类不能为空");
    
    Method oriMethod = class_getInstanceMethod(cls, oriSEL);
    Method swiMethod = class_getInstanceMethod(cls, swizzledSEL);
    
    if (!oriMethod) {
        // 在oriMethod为nil时,替换后将swizzledSEL复制一个不做任何事的空实现,代码如下:
        class_addMethod(cls, oriSEL, method_getImplementation(swiMethod), method_getTypeEncoding(swiMethod));
        method_setImplementation(swiMethod, imp_implementationWithBlock(^(id self, SEL _cmd){ }));
    }
    
    // 一般交换方法: 交换自己有的方法 -- 走下面 因为自己有意味添加方法失败
    // 交换自己没有实现的方法:
    //   首先第一步:会先尝试给自己添加要交换的方法 :personInstanceMethod (SEL) -> swiMethod(IMP)
    //   然后再将父类的IMP给swizzle  personInstanceMethod(imp) -> swizzledSEL
    //oriSEL:personInstanceMethod

    BOOL didAddMethod = class_addMethod(cls, oriSEL, method_getImplementation(swiMethod), method_getTypeEncoding(swiMethod));
    if (didAddMethod) {
        class_replaceMethod(cls, swizzledSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
    }else{
        method_exchangeImplementations(oriMethod, swiMethod);
    }
    
}
+ (void)load{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [LGRuntimeTool lg_bestMethodSwizzlingWithClass:self oriSEL:@selector(helloword) swizzledSEL:@selector(lg_studentInstanceMethod)];
    });
}
上一篇 下一篇

猜你喜欢

热点阅读