美文网首页iOS面试题/2019ios学习
iOS底层原理 16 :底层面试题

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

作者: smooth_lgh | 来源:发表于2020-10-23 18:31 被阅读0次
    1. 主类的方法和分类的方法重名,会如何调用?
    • 如果重名的是+load方法,则先执行父类的load方法 ,其次主类的load方法,最后执行分类的load方法

    • 如果重名的是+initialize,执行父类的initialize方法,然后分类的initialize方法会覆盖主类的initialize方法,导致主类的initialize方法不执行。 (initialize是在对象第一次发送消息的时候调用)

    • 如果重名的是其他普通方法,则分类方法会覆盖主类方法

    2.方法的本质?sel是什么?imp是什么?两者之间的关系又是什么?


    3. Runtime是如何实现weak,为什么可以自动置为nil?
    • 通过SideTable找到我们的weak_table
    • weak_table根据referent找到或者创建weak_entry_t
    • 然后append_referrer(entry,referrer)将我的新弱引用的对象加到entry
    • 最后weak_entry_insert 把entry加入到我们的weak_table
    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)];
        });
    }
    

    相关文章

      网友评论

        本文标题:iOS底层原理 16 :底层面试题

        本文链接:https://www.haomeiwen.com/subject/sayvmktx.html