Category的底层数据结构
Category编译后,其本质是一个结构体

struct _category_t {
    const char *name; // 类名(Person)
    struct _class_t *cls;  // 类对象指针(指向Person类对象)
    const struct _method_list_t *instance_methods; // 实例方法列表
    const struct _method_list_t *class_methods; // 类方法列表
    const struct _protocol_list_t *protocols; // 协议列表
    const struct _prop_list_t *properties; // 属性列表
  };

结论:
通过结构体可知,可以添加属性,方法,协议。不能添加成员变量;

Category添加属性

1:普通的类添加一个属性,系统会帮我们实现:创建一个成员变量_name; 生成setter、getter方法的声明;生成setter、getter方法的实现;
2:category不会创建成员变量;不会生成setter、getter方法的实现;

因此:直接添加属性,是不能使用的;

- (void)setSportEndTime:(NSDate *)sportEndTime
{
    objc_setAssociatedObject(self, @selector(sportEndTime), sportEndTime, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSDate *)sportEndTime
{
    return objc_getAssociatedObject(self, _cmd);
}

Category关联到对应的类

程序运行时,runtime会将category的数据合并到对应的类中;
按编译倒序将各分类中的方法,协议,属性分别整合成一个二维数组,然后讲整合后的分类信息附加到原类中;

如果多个Category中存在了重复的方法,怎么办
多个分类存在的情况下,受编译顺序的影响;
通过调整Targets -> Build Phases -> Compile Sources 中文件的顺序,可以调整编译顺序;

参考链接:
https://www.jianshu.com/p/296aeaa1bad1
https://www.jianshu.com/p/3d954fcd7259