更深入地了解Apple文档,我发现了有关dlopen命令的信息,该命令用于在某些情况下链接库,具体取决于系统版本和支持的库。
dlopen的使用示例:
函数'dlopen()'是私有API吗?
因此,让我们看一下Apple Docs提供的解决方案:
将包含应用程序部署到旧版本的iOS
如果从包含的应用程序链接到嵌入式框架,则即使嵌入式框架在这些版本中不可用,仍可以将其部署到8.0之前的iOS版本。
允许您执行此操作的机制是dlopen命令,您可以使用该命令有条件地链接和加载框架包。您可以使用此命令来替代可以在Xcode General或Build Phases目标编辑器中指定的构建时链接。主要思想是仅在iOS 8.0或更高版本中运行时,才将嵌入式框架链接到您的包含应用程序。
您必须使用Objective-C,而不是Swift在有条件地加载框架包的代码语句中。应用程序的其余部分可以用任何一种语言编写,嵌入式框架本身也可以用任何一种语言编写。
调用dlopen之后,使用以下类型的语句访问嵌入式框架类:
MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init];
重要
如果包含的应用程序目标链接到嵌入式框架,则它必须包含arm64体系结构,否则它将被App Store拒绝。
设置应用扩展Xcode项目以利用条件链接
- 通常,对于每个包含的应用程序扩展,将部署目标设置为iOS 8.0或更高版本。在Xcode目标编辑器的“常规”选项卡的“部署信息”部分中执行此操作。
- 对于包含的应用程序,将部署目标设置为要支持的最旧的iOS版本。
- 在您所包含的应用程序中,使用systemVersion方法在运行时检查中对dlopen命令的条件化检查iOS版本。仅当所包含的应用程序在iOS 8.0或更高版本中运行时,才调用dlopen命令。进行此调用时,请确保使用Objective-C,而不是Swift。
某些iOS API通过dlopen命令使用嵌入式框架。您必须像直接调用dlopen一样,限制对这些API的使用。这些API来自CFBundleRef不透明类型:
CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames
从NSBundle类中:
加载
loadAndReturnError:
classNamed:
在要部署到8.0之前的iOS版本的包含应用程序中,仅在确保您在iOS 8.0或更高版本中运行的运行时检查中调用这些API,然后使用Objective-C调用这些API。