一.面试题
相信大家在面试的时候经常会被问到Category的实现原理,以及Category为什么只能加方法不能加属性?个人理解这个问题本身问的就有问题,首先我们看分类的底层代码:
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(boolisMeta) {
if(isMeta)returnclassMethods;
elsereturninstanceMethods;
}
property_list_t*propertiesForMeta(boolisMeta,structheader_info *hi);
};
通过上面的分类底层代码我们可以找到category_t 结构体,它里面包含了对象方法,类方法,协议,属性,既然分类的底层代码里面已经包含了属性,为什么我们面试的时候会被问到分类为什么不能添加属性?下面我们来揭开它的神秘面纱
1.首先我们创建一个person类,再给penson类创建一个分类Person+TCText,在分类的.h文件
这么写工程是不会报任何错误,给我们一种表面上其实是可以添加属性的,写上一个属性,系统会自动帮我们生成setter和getter方法,在分类里面写属性或者成员变量,系统只会帮我们做的一件事情就是它只会声明我们的setter和getter方法,不会帮我们实现,上面的这个属性等同于我们在分类里面写
无论上面何种写法,我们在ViewController都能访问TCName这个属性
但是,当我们在分类里面重写settet或者getter的时候,它就会出现:
为什么什么会报错了?因为分类的属性,系统不会自动帮我们生成_TCName(相关属性赋值可以看苹果官网API,这里不做解释),在这里我们如果写:
表面看上去不会报错,但是当外部访问TCName的时候,就会发现:
程序一旦运行起来,就会因为递归,程序闪退。