属性和实例变量间的关系

  • “属性”(property)是 Objective-C 的一项特性,用于封装对象中的数据。 Objective-C 对象通常会把所需要的数据保存为各种实例变量。实例变量一般通过“存取方法”来访问。其中,“获取方法”(getter)用于读取变量值,而“设置方法“(setter)用于写入变量值。开发者可以利用“属性”这一特性令编译器自动编写与属性相关的存取方法,此特性引入了一种新的“点语法”,使开发者可以更为容易地依照类对象来访问存放于其中的数据。

  • 一个问题:如果代码中实例变量使用了编译期计算出的偏移量,那么修改类定义之后必须重新编译,否则就会出错。例如,某个代码库中的代码使用了一份旧的类定义,如果和其链接的代码使用了新的类定义,那么运行时就会出现不兼容现象。

    Objective-C 的做法是:把实例变量当作一种存储偏移量所用的“特殊变量”,交由“类对象”(class object)保管。偏移量会在运行期查找,如果类的定义变了,那么存储的偏移量也变了,这样的话,无论何时访问实例变量,总能使用正确的偏移量。 甚至可以在运行期向类中新增实例变量,这就是“稳固的”(notfragile)“应用程序二进制接口”(Application Binary Interface, ABI)。ABI定义了许多内容,其中一项就是生成代码时应遵循的规范。有了这种“稳固的”(nonfragile)的ABI,我们就可以在类扩展(Extensions / class-continuation)或实现文件中定义实例变量了。

    所以说,不一定要在接口中把全部实例变量都声明好,可以将某些变量从接口的 public 区段(C++ 和 JAVA 中的写法)里移走,以便保护与类实现有关的内部信息。

    关于Non Fragile ivars这个特性的介绍可以看这篇文章:Objective-C类成员变量深度剖析

  • 编译器会把“点语法”转换为对存取方法对调用,使用“点语法”对效果和直接调用存取方法之间没有丝毫差别。在赋值语句等号之前调用“点语法”相当于调用 setter 方法,而在其他地方调用“点语法”则相当于调用 getter 方法。

  • 属性还有更多优势,如果使用了属性的话,那么编译器就会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。需要强调的是,找个过程由编译器在编译期执行,所以编译器里看不到这些“合成方法”的源代码。

    除了生成方法代码之外,编译器还要自动向类中添加适当的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。 也可以在类的实现代码里通过@synthesize语法来指定实例变量的名字。

  • 若不想令编译器自动合成存取方法,则可以自己实现。如果你只实现了其中一个存取方法,那么另外一个还是会由编译器来合成。

    还有一种方法能阻止编译器自动合成存取方法,就是使用@dynamic关键字,它会告诉编译器:不要自动创建实现属性所用的实例变量,也不要为其创建存取方法。而且,在编译访问属性的代码时,即使编译器发现没有定义存取方法,也不会报错,它相信这些方法能在运行期找到。但如果当程序运行到相应代码段时,没有找到相应的存取方法,会导致程序崩溃。

属性 VS 实例变量的优缺点对比

1.在访问效率上的比较 ------实例变量完胜
“属性” VS “实例变量”

概念示意图

2.在内存管理语义上的比较 ------属性完胜

“属性” VS “实例变量”

概念示意图

3.KVO触发机制上的比较 ------- 属性略胜

直接访问实例变量,无法触发KVO机制,这一点需要根据具体业务来和对象具体的行为来决定。

“属性” VS “实例变量”

概念示意图

4.在调试错误上的比较 ------ 属性胜
通过属性来访问可以来帮助排查与之相关的错误,因为我们有机会在set/get方法中增加断点,而实例变量无法做到。

根据具体场景来决定声明实例变量还是属性

  • 在对象内部读取数据时,应该直接通过实例变量来读,而写入数据时,则应通过属性来写。
  • 在初始化方法及dealloc方法中,总是应该直接通过实例变量来读写数据。
  • 使用懒加载初始化时,需要通过属性来读取数据。

参考博客:iOS巩基之 不再纠结实例变量&属性

相关文章:

  • 2022-01-19
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-16
  • 2022-12-23
  • 2022-12-23
  • 2021-09-14
猜你喜欢
  • 2022-12-23
  • 2022-01-10
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案