首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS RunTime之五:Category 面试题

iOS RunTime之五:Category 面试题

作者头像
s_在路上
发布2018-09-11 17:10:48
1.6K0
发布2018-09-11 17:10:48
举报
文章被收录于专栏:iOS 开发杂谈iOS 开发杂谈

面试题:为什么 Category 中不能动态添加成员变量?

解答:

很多人在面试的时候都会被问到 Category,既然允许用 Category 给类增加方法和属性,那为什么不允许增加成员变量?

Objective-C 提供的 runtime 函数中,确实有一个 class_addIvar() 函数用于给类添加成员变量,但是阅读过苹果的官方文档的人应该会看到:

This function may only be called after objc_allocateClassPair and before objc_registerClassPair. Adding an instance variable to an existing class is not supported.

大概的意思说,这个函数只能在“构建一个类的过程中”调用。当编译类的时候,编译器生成了一个实例变量内存布局 ivar layout,来告诉运行时去那里访问类的实例变量们,一旦完成类定义,就不能再添加成员变量了。经过编译的类在程序启动后就被 runtime 加载,没有机会调用 addIvar。程序在运行时动态构建的类需要在调用 objc_registerClassPair 之后才可以被使用,同样没有机会再添加成员变量。

Paste_Image.png

从运行结果中看出,你不能为一个类动态的添加成员变量,可以给类动态增加方法和属性。

因为方法和属性并不“属于”类实例,而成员变量“属于”类实例。我们所说的“类实例”概念,指的是一块内存区域,包含了 isa 指针和所有的成员变量。所以假如允许动态修改类成员变量布局,已经创建出的类实例就不符合类定义了,变成了无效对象。但方法定义是在 objc_class 中管理的,不管如何增删类方法,都不影响类实例的内存布局,已经创建出的类实例仍然可正常使用。

同理:

Paste_Image.png

某一个类的分类是在 runTime 时,被动态的添加到类的结构中。

想了解分类是如何加载的请看 iOS RunTime之六:Category

Category Extension 的区别
  • Extension 在编译期决议,它就是类的一部分,在编译期和头文件里的 @interface 以及实现文件里的 @implement 一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。Extension 一般用来隐藏类的私有信息,你必须有一个类才能为这个类添加 Extension,所以你无法为系统的类比如 NSString 添加 Extension
  • Category 则完全不一样,它是在运行期决议的。
  • Extension 可以添加成员变量,而 Category 一般不可以。

总之,就 CategoryExtension 的区别来看,Extension 可以添加成员变量,而 Category 是无法添加成员变量的。因为 Category 在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局。

面试题

一般面试官有时候会问到这样的问题:

在类和Category中都可以有study方法,那么有两个问题:

  • 在类的study方法调用的时候,我们可以调用Category中声明的study方法么?
  • 如果一个类有多个分类的时候study方法,调用顺序是咋样的呢?

解决方法:

iOS之+load和+initialize的区别

如果有觉得上述我讲的不对的地方欢迎指出,大家多多交流沟通。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.09.21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Category 和 Extension 的区别
    • 面试题
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档