美文网首页
分类和类扩展小结

分类和类扩展小结

作者: Abner_XuanYuan | 来源:发表于2021-05-12 15:03 被阅读0次

1. category

category_t 结构体构成

struct category_t {
    const char *name;
    classref_t cls;
    struct method_list_t *instanceMethods;                 // 对象方法
    struct method_list_t *classMethods;                    // 类方法
    struct protocol_list_t *protocols;                     // 协议
    struct property_list_t *instanceProperties;            // 属性
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties;

    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) return classMethods;
        else return instanceMethods;
    }

    property_list_t *propertiesForMeta(bool isMeta, struct header_info *hi);
};

分析:
1 分类是一个包含对象方法,类方法,协议,属性等的结构体,因此,可以在分类中添加对象方法,类方法,协议等.
2 分类是将结构体中的方法列表等拷贝到原类对象的方法列表中.
3 分类中可以添加属性,但是并不会自动生成成员变量及set、get方法,因为 category_t 结构体不存在成员变量列表.
4 成员变量是存放在实例对象里的,并在编译阶段就已经决定好了,而分类是在运行时才去加载的.我们无法在程序运行时将分类的成员变量添加到实例对象的结构体中,因此分类中不能添加成员变量.

2. Extension

Extension 是一种特殊的分类.类扩展与分类相比只少了分类的名称,所以称之为“匿名分类”.一般用来扩展私有属性和方法.

3. 分类和扩展之间的区别

  1. 分类不可以直接添加属性,但可以通过 runtime 添加,扩展可以直接添加属性.
  2. 如果分类中有和原有类同名的方法, 会优先调用分类中的方法,也就是说会忽略原有类的方法.所以同名方法调用的优先级为: 分类 > 本类 > 父类.
  3. 如果多个分类中都有和原有类中同名的方法, 那么调用该方法的时候执行谁由编译器决定,编译器会执行最后一个参与编译的分类中的方法(可以在 buildPhases -> Compile Sources 里面调整编译顺序).
  4. Extension 只能用于自身类,而不能用于子类或者其他地方.
  5. Extension 中声明的方法必须要实现,否则编译器警告.Category 不会.这是因为 Extension 是编译阶段被添加到类中,Category 是运行时被添加到类中.

4.Category 添加属性

方案一

在.h中
@property(nonatomic,copy) NSString *name;

在.m中
static NSString *_name;
-(void)setName:(NSString *)name{
    _name = name;
}
-(NSString *)name{
    return _name;
}
方案二
在.h中
@property(nonatomic,copy)NSString *age;

在.m中
-(void)setAge:(NSString *)age{
    //参数一:给那个对象添加属性
    //参数二:属性名
    //参数三:关联的值,也就是set方法存入值给属性去保存
    //策略
    objc_setAssociatedObject(self, @"age",age, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)age{
    return objc_getAssociatedObject(self, @"age");
}

分类关联对象:关联对象并不是存储在被关联对象本身内存中,而是存储在全局的统一的一个 AssociationsManager 中.如果设置关联对象为nil,就相当于是移除关联对象.

补充: load 和 initialize 的区别

  1. load 方法是在 pre-main 阶段装载类信息的时候就调用;initialize 是在类第一次接收到消息的时候调用
  2. load 方法的调用顺序为父类 --> 子类 --> 分类;initialize 调用顺序为父类 --> 子类或者分类,且父类 initialize 只会调用一次,分类的 initialize 会覆盖子类的 initialize.
  3. load 方法是通过 isa 指针找到对应的方法与实现;initialize 方法是通过 runtime 的消息转发机制调用.
  4. load 方法一般用于方法交换;initialize 方法一般用于初始化全局变量或静态变量.
  5. load方法不可以继承; initialize 可以.

相关文章

  • 分类和类扩展小结

    1. category 2. Extension Extension 是一种特殊的分类.类扩展与分类相比只少了分类...

  • 分类和类扩展

    类扩展 (ClassExtension也有人称为匿名分类) 作用 使用方法 分类(Categories) 作用 使...

  • 分类和类扩展

    1、分类实现原理 Category编译之后的底层结构是struct category_t,里面存储着分类的对象方法...

  • iOS基础问答面试题连载(一)

    1.简单的描述下类扩展和分类的区别?(说2点) 类扩展没有名字,分类有名字 类扩展可以为某个类增加额外的属性、成员...

  • iOS基础问题面试题附带答案(一)

    1.简单的描述下类扩展和分类的区别?(说2点) 类扩展没有名字,分类有名字。类扩展可以为某个类增加额外的属性、成员...

  • iOS知识基础篇

    category 和 extension 的区别 分类有名字,类扩展没有分类名字,是一种特殊的分类 分类只能扩展方...

  • IOS知识基础篇

    category 和 extension 的区别 分类有名字,类扩展没有分类名字,是一种特殊的分类 分类只能扩展方...

  • 1. iOS面试题基础篇

    category 和 extension 的区别 分类有名字,类扩展没有分类名字,是一种特殊的分类 分类只能扩展方...

  • iOS面试题-基础篇

    category 和 extension 的区别 分类有名字,类扩展没有分类名字,是一种特殊的分类 分类只能扩展方...

  • iOS面试题--基础篇

    category 和 extension 的区别 分类有名字,类扩展没有分类名字,是一种特殊的分类 分类只能扩展方...

网友评论

      本文标题:分类和类扩展小结

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