美文网首页
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