返回

OC 类中属性的底层实现原理

IOS

前言

在上一篇文章中,我们深入探索了 OC 类的本质。而在本文中,我们将把目光投向类的另一个重要组成部分——属性,探究其在底层的实现原理。

属性的本质

在 OC 中,属性本质上是类的数据成员,但又不仅仅如此。它们提供了面向对象的语法糖,允许我们以一种更简洁、更优雅的方式来访问和操作类的内部数据。

属性的底层实现

当我们定义一个属性时,编译器会自动生成一个私有实例变量和一对 setter/getter 方法。这些方法的实现取决于属性的类型和修饰符。

内存平移赋值

对于简单类型(如 int、float、BOOL),setter 方法通常会直接将值赋给相应的实例变量。这种赋值操作称为内存平移赋值。

例如,对于以下属性:

@property int age;

编译器会生成以下 setter 方法:

- (void)setAge:(int)newAge {
  age = newAge;
}

objc_setProperty 方法

对于复杂类型(如对象),setter 方法通常会调用 objc_setProperty 方法来设置值。

objc_setProperty 方法的签名如下:

void objc_setProperty(id object, const char *name, id value, BOOL atomic);
  • object: 要设置属性的对象
  • name: 属性的名称(C 字符串)
  • value: 要设置的值
  • atomic: 是否以原子方式设置属性(线程安全)

对于以下属性:

@property NSString *name;

编译器会生成以下 setter 方法:

- (void)setName:(NSString *)newName {
  objc_setProperty(self, "name", newName, YES);
}

setter 方法的特殊情况

在某些情况下,setter 方法可能会有特殊的实现。例如:

属性合成

当属性没有明确实现 setter 方法时,编译器会自动合成一个默认的 setter 方法。该方法只负责调用 objc_setProperty 方法。

只读属性

对于只读属性,编译器不会生成 setter 方法。

原子属性

对于声明为 atomic 的属性,setter 方法会在加锁的情况下设置值,以保证线程安全。

结论

通过本文的深入分析,我们揭开了 OC 类中属性底层实现的神秘面纱。从内存平移赋值到 objc_setProperty 方法的调用,我们对属性的理解又上升了一个层次。这些知识将有助于我们编写更高质量、更健壮的 OC 代码。

附录

延伸阅读