返回

剖析iOS底层奥秘:类扩展与关联对象的运作原理

IOS

前言

iOS底层原理之OC类的加载原理(下)中,我们已经分析了分类加载的流程,以及主类和分类搭配加载的情况。本文将继续深入剖析Objective-C中的特殊分类——类扩展,以及分类属性的存取方式——关联对象。

准备工作

为了更好地理解本文的内容,请确保您已经阅读过前文并对以下知识有一定了解:

  • Objective-C中的类和对象
  • Objective-C中的分类
  • Objective-C的运行时机制

如果您还没有阅读过前文或对上述知识还不熟悉,强烈建议您先补习一下,以便更好地理解本文的内容。

类扩展

类扩展是一种特殊的分类,它允许您向现有类添加新方法、属性和其他成员,而无需修改类的源代码。这在某些情况下非常有用,例如:

  • 您想向一个第三方类添加新的功能,但您无法修改该类的源代码。
  • 您想向一个系统类添加新的功能,但您不想修改系统的文件。
  • 您想向一个类添加一些临时性的功能,而这些功能不值得创建一个新的子类。

类扩展的语法与普通分类类似,但它有一个特殊的@interface来声明类扩展。例如,以下代码扩展了NSString类,添加了一个名为reverse的新方法:

@interface NSString (Reverse)

- (NSString *)reverse;

@end

在类扩展中定义的方法、属性和其他成员与在普通分类中定义的成员一样,都可以在类的实例中使用。例如,以下代码使用类扩展添加的reverse方法来反转一个字符串:

NSString *str = @"Hello, World!";
NSString *reversedStr = [str reverse];
NSLog(@"%@", reversedStr); // 输出:"!dlroW ,olleH"

关联对象

关联对象是一种将任意数据与Objective-C对象关联起来的技术。这在某些情况下非常有用,例如:

  • 您想在对象中存储一些私有数据,但您不想将其作为对象的属性。
  • 您想在对象中存储一些临时数据,而这些数据不值得创建一个新的属性。
  • 您想在对象中存储一些与其他对象相关的数据。

关联对象的语法如下:

objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);

其中:

  • object是要与数据关联的对象。

  • key是一个唯一标识符,用于在对象中查找关联的数据。

  • value是要与对象关联的数据。

  • policy指定了关联数据的策略,有四种可选值:

    • OBJC_ASSOCIATION_ASSIGN:将数据与对象关联,当对象被释放时,数据也会被释放。
    • OBJC_ASSOCIATION_RETAIN:将数据与对象关联,当对象被释放时,数据不会被释放。
    • OBJC_ASSOCIATION_COPY:将数据的副本与对象关联,当对象被释放时,数据副本也会被释放。
    • OBJC_ASSOCIATION_COPY_NONATOMIC:与OBJC_ASSOCIATION_COPY类似,但它是非原子的,这意味着它可以在多线程环境中使用。

关联对象可以通过以下代码获取:

id value = objc_getAssociatedObject(id object, const void *key);

以下代码示例演示了如何使用关联对象将数据与对象关联起来:

// 定义一个关联键
const void *key = &"my_key";

// 将数据与对象关联
objc_setAssociatedObject(self, key, @"Hello, World!", OBJC_ASSOCIATION_RETAIN);

// 获取与对象关联的数据
NSString *value = objc_getAssociatedObject(self, key);

// 使用与对象关联的数据
NSLog(@"%@", value); // 输出:Hello, World!

结语

类扩展和关联对象都是Objective-C中非常有用的特性,它们可以帮助您扩展现有类或向对象添加额外的数据。理解这些特性的原理和用法对于提高您的Objective-C编程技能非常重要。