注册

iOS Category---为什么只能加方法不能加属性

一.面试题

            相信大家在面试的时候经常会被问到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文件

419dec8ae5b3c6c4c8132251e8de523b.png


这么写工程是不会报任何错误,给我们一种表面上其实是可以添加属性的,写上一个属性,系统会自动帮我们生成setter和getter方法,在分类里面写属性或者成员变量,系统只会帮我们做的一件事情就是它只会声明我们的setter和getter方法,不会帮我们实现,上面的这个属性等同于我们在分类里面写

6c6163e910ae5fc1b4f72a6f5c180f8d.png


无论上面何种写法,我们在ViewController都能访问TCName这个属性
c3d0763fac80b25da100771f3fff2ccc.png

但是,当我们在分类里面重写settet或者getter的时候,它就会出现:

f42dc8cea99583237a0f2c611b365b50.png

为什么什么会报错了?因为分类的属性,系统不会自动帮我们生成_TCName(相关属性赋值可以看苹果官网API,这里不做解释),在这里我们如果写:

3c88ff3f562e7fac8b1a9bd56eebe02a.png


表面看上去不会报错,但是当外部访问TCName的时候,就会发现:
ff2333fe6c29601a9b20039f6ddd6c7c.png


程序一旦运行起来,就会因为递归,程序闪退。

总结:不是说分类不能添加属性,是因为分类可以添加属性,但是由于系统不会自动帮分类的属性实现getter和setter方法,也不会帮其生成_TCName,无论你重写settet或者getter还是,你不能通过self.TCName去访问属性,重写了setter,这么访问就会发生递归,直接导致程序闪退。所以下次你该知道怎么回答面试官的问题了吧!!!



作者:枫紫_6174
链接:https://www.jianshu.com/p/49d131c61348








0 个评论

要回复文章请先登录注册