如何创建一个 Library/Framework ,只有在编译时存在时才会被链接和使用
How to create a Library/Framework that will be linked and used only if present at compile time
我有兴趣复制您在 Apple 框架中看到的那种功能:应用程序可以利用更新版本 iOS 上的新框架,但在缺少它们时不会失败.
当然,如果有另一种解决问题的方法,我很乐意看到它。
我所在的位置如下:
公司 A 向第三方提供 iOS 框架(以下称为 FrameA),他们可以 link 进入他们的应用程序。
我的任务是创建一个可选模块,该模块可以 "bolted on" 到 FrameA,但实际上并不是它的一部分(这是因为 FrameA 经常针对不同的客户和其他业务进行更新和定制限制)。
第三方可以选择是否使用附加库(或框架,或任何可以工作的)。如果它存在,FrameA 必须 link 它并且代码执行它的功能。如果它不存在,那么 FrameA 会像现在一样继续。它必须适用于接收新版本 FrameA 而不是附加库的第三方。
我应该尽可能少地对 FrameA 进行更改,因为这些更改必须由另一个团队继续维护。
我还需要在 Apple 的提交规则中执行此操作,解决方案必须至少支持 iOS6、7 和 8。因此不允许动态 linking。
A公司直接向第三方提供FrameA,所以Apple唯一需要认可的部分就是最终的App。
这种事情我小范围做过,还不错
在 FrameA 中,使用工厂实例化所有 bolt-on objects。工厂使用 NSClassFromString()
动态获取 class。避免 class 方法:这会让事情变得更难。尽可能使用协议而不是 classes:这使事情变得更容易。
- (id<FABoltOnProtocol>)createBoltOnClass
{
return [[NSClassFromString(@"BOBoltOnClass") alloc] init];
}
此代码将 运行 即使 BOBoltOnClass
未链接到最终应用程序。 NSClassFromString(@"BOBoltOnClass")
将 return Nil
、[Nil alloc]
returns nil
和 [nil init]
returns nil
.
您可以用同样的方法测试 bolt-on 是否存在。
BOOL MyHasBoltOn
{
return NSClassFromString(@"BOBoltOnClass") != Nil;
}
缺点是必须使用 bolt-on 中的 headers 编译 FrameA。这就是我推荐协议的原因。这些协议可以由 FrameA 拥有并且 bolt-on 将遵守它(注意:我通过使用 FrameA 的前缀 FA 和 class 与 bolt-on 的前缀 BO 命名协议来暗示这一点) .
最后,作为一个字符串,您可以从配置文件中读取@"BOBoltOnClass",这样您就可以根据需要交换不同的bolt-on。
请注意必须设置构建标志 -ObjC,否则编译器将不会加载 bolt-on classes 的符号,因为它们不是常规调用的.
我有兴趣复制您在 Apple 框架中看到的那种功能:应用程序可以利用更新版本 iOS 上的新框架,但在缺少它们时不会失败.
当然,如果有另一种解决问题的方法,我很乐意看到它。
我所在的位置如下:
公司 A 向第三方提供 iOS 框架(以下称为 FrameA),他们可以 link 进入他们的应用程序。
我的任务是创建一个可选模块,该模块可以 "bolted on" 到 FrameA,但实际上并不是它的一部分(这是因为 FrameA 经常针对不同的客户和其他业务进行更新和定制限制)。
第三方可以选择是否使用附加库(或框架,或任何可以工作的)。如果它存在,FrameA 必须 link 它并且代码执行它的功能。如果它不存在,那么 FrameA 会像现在一样继续。它必须适用于接收新版本 FrameA 而不是附加库的第三方。 我应该尽可能少地对 FrameA 进行更改,因为这些更改必须由另一个团队继续维护。
我还需要在 Apple 的提交规则中执行此操作,解决方案必须至少支持 iOS6、7 和 8。因此不允许动态 linking。 A公司直接向第三方提供FrameA,所以Apple唯一需要认可的部分就是最终的App。
这种事情我小范围做过,还不错
在 FrameA 中,使用工厂实例化所有 bolt-on objects。工厂使用 NSClassFromString()
动态获取 class。避免 class 方法:这会让事情变得更难。尽可能使用协议而不是 classes:这使事情变得更容易。
- (id<FABoltOnProtocol>)createBoltOnClass
{
return [[NSClassFromString(@"BOBoltOnClass") alloc] init];
}
此代码将 运行 即使 BOBoltOnClass
未链接到最终应用程序。 NSClassFromString(@"BOBoltOnClass")
将 return Nil
、[Nil alloc]
returns nil
和 [nil init]
returns nil
.
您可以用同样的方法测试 bolt-on 是否存在。
BOOL MyHasBoltOn
{
return NSClassFromString(@"BOBoltOnClass") != Nil;
}
缺点是必须使用 bolt-on 中的 headers 编译 FrameA。这就是我推荐协议的原因。这些协议可以由 FrameA 拥有并且 bolt-on 将遵守它(注意:我通过使用 FrameA 的前缀 FA 和 class 与 bolt-on 的前缀 BO 命名协议来暗示这一点) .
最后,作为一个字符串,您可以从配置文件中读取@"BOBoltOnClass",这样您就可以根据需要交换不同的bolt-on。
请注意必须设置构建标志 -ObjC,否则编译器将不会加载 bolt-on classes 的符号,因为它们不是常规调用的.