如果您与包含类别的静态库链接,则链接器会将所有类别代码复制到您的可执行文件中。如果您与共享库链接,则共享库的整个代码段将映射到您的进程的地址空间,但它是延迟分页的,因此您实际上可能不会从磁盘中读取所有类别代码,除非您全部使用它。
但我认为这并不是该页面真正在谈论的内容。
链接时库
首先,让我们谈谈您告诉链接器链接您的应用程序的库。
考虑NSString
。该类NSString
在 Foundation 框架中定义,该框架充满了通用类,这些类在具有 GUI 的程序和没有 GUI 的程序中很有用。因此NSString
,Foundation 中定义的类不包含任何用于将字符串绘制到图形上下文中的代码,因为该代码(通常)在非 GUI 应用程序中是无用的。
AppKit 框架(在 OS X 上)管理一个 GUI。在 GUI 中能够将字符串绘制到图形上下文中很有用,因此 AppKit 包含一个类别,NSString
用于添加绘制字符串的方法,例如drawAtPoint:withAttributes:
. UIKit(在 iOS 上)做同样的事情(但方法有点不同)。
因此,如果您在 OS X 上编写程序并使用 Foundation 但不使用 AppKit,您的进程将不会加载 AppKitNSString
类别,并且您不会为NSString
.
对于像 AppKit 这样的共享库,在现代硬件上的价格是微不足道的。
现在,您可以使用自己的库做同样的事情,您可以将其设为静态。假设您创建了一个“TwitterModel”库来与 Twitter 交谈。它充满了模拟你在 Twitter 上找到的东西的类,比如帐户和推文。但是您不包含用于管理 GUI 以显示推文的代码。
相反,您创建了另一个库“TwitterGUI”,它(除了定义更多类)使用类别将方法添加到“TwitterModel”库中的模型类。
如果您编写一个链接到 TwitterGUI 和 TwitterModel 的程序,可执行文件将包含来自这两个库的所有 Objective-C 代码。但是,如果您编写一个仅命令行程序(无 GUI)并且仅将其与 TwitterModel 链接,则该程序将不包含任何与 GUI 相关的代码。哦,储蓄!
运行时库
现在让我们考虑您没有告诉链接器链接您的应用程序的共享库。
您可以在运行时使用 APIdlopen
或-[NSBundle load]
. 如果库包含类别,这些类别将添加到您正在运行的程序中的类中。
因此,您可以通过尝试以编程方式加载库来使您的应用程序有选择地使用共享库(如果用户系统上存在共享库)。如果成功,您可以调用您知道库定义的任何类别方法。(当然,您可以使用库提供的类,如果有的话。)如果您无法加载库,请小心避免从库中调用任何这些类别方法。
但是,通常情况下,我们使用动态加载 API 来加载插件,并且插件提供了一些类,这些类是基类的子类,或者符合我们专门为要实现的插件定义的协议。我们只需要获取该类的名称,然后我们创建它的一个实例并将我们在基类或协议中定义的消息发送给它。