美文网首页
Category中添加属性名冲突了怎么办

Category中添加属性名冲突了怎么办

作者: 柳爷在深圳 | 来源:发表于2016-11-01 23:53 被阅读182次

    Category的同名方法覆盖并不是真的其他同名方法就消失了,而是因为系统调用方法的时候根据方法名在method_list中查找方法,找 到第一个名字匹配的方法之后就不继续往下找了。所以每次调用的都是method_list中最前面的同名方法。实际其他同名方法还在 method_list中。
    所以我们可以根据selector查找到所有的同名method,然后调用

    static inline void __invoke_all_method(id self, SEL selecotr) 
    {  
        //1. 根据self,获取class Class class = object_getClass(self); 
         //2. 获取方法列表 uint count; Method *methodList = class_copyMethodList(class, &count); 
        //3. 遍历方法列表 for (int i = 0; i < count; i++) 
        {
             Method method = methodList[i];
             //4. 根据SEL查找方法 
            if (!sel_isEqual(selecotr, method_getName(method)))
             { continue; }
             //5. 获取方法的实现
             IMP implement = method_getImplementation(method); 
            //6. 直接调用方法的实现
             ((void(*)(id,SEL))implement)(self, selecotr); 
        } 
    } 
    
    + (void)invokeAllClassMethodWithSelector:(SEL)selector 
    {
         __invoke_all_method(self, selector); 
    }
    

    根据刚刚介绍的原理,我们封装了一个通过selector调用所有同名method的方法。

    • 根据self,获取class,如果self是实例方法的self,这里获取的是普通的class,如果self是类方法的self,这里获取的是metaClass。实例方法存放在普通class中,类方法存放在metaClass中。了解更多请看iOS开发RunTime之函数调用
    • 通过class_copyMethodList获取class的方法列表。如果class传的是metaClass,获取的是类方法的方法列表,如果class是普通class,获取的是实例方法的方法列表。
    • 遍历methodList
    • 根据SEL查找method
    • 获取IMP
    • 直接调用IMP

    在系统的+initialize中,我们用invokeAllClassMethodWithSelector调用自定义 的+categoryInitialize。这时候,在category的+categoryInitialize中添加属性,就不怕Category覆盖了。

    相关文章

      网友评论

          本文标题:Category中添加属性名冲突了怎么办

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