iOS框架弱链接:未定义的符号错误

我正在构build我自己的框架,build议分发给其他开发人员包括他们的项目。 这个框架可选地链接某些框架(例如CoreLocation)。 问题是,当我将框架链接到在构build阶段中不包含CoreLocation的真正的独立项目时,当尝试构build此主机项目时,出现链接器错误,如“未定义的架构符号”

Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_CLLocationManager", referenced from: objc-class-ref in MySDK(MyServerConnection.o) ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) 

是否有可能避免这种情况,因为我不想强迫开发人员将CoreLocation包含到他们的项目中? 其实,我知道这是可能的,但是我应该怎么做才能做到呢?

从你的问题的描述中,我假设你已经知道如何通过将Xcode设置为“可选”来使Xcode与框架弱连接 。

您需要解决两个问题:类可用性和符号可用性。 Apple在“ 框架编程指南:框架和弱链接”以及“ SDK兼容性指南:使用基于SDK的开发”中介绍了这一点

课程可用性

这非常简单:使用NSClassFromString()来查看当前环境中的类是否可用。

 if (NSClassFromString("CLLocationManager") != NULL){ 

如果该类可用,则可以实例化并发送消息,否则不能。

符号可用性

你特别感兴趣的是使用弱链接框架的常量或结构。 一个C风格的函数将是类似的,但使用CoreLocation时不担心。 我们将以CoreLocation常量为例。

每次你使用它,你必须检查,以确保它存在:

 if (&kCLErrorDomain != NULL){ // Use the constant } 

请注意, &采用常量的地址进行比较。 另外请注意,你不能这样做:

 if (kCLErrorDomain){ // Use the constant } 

或这个:

 if (&kCLErrorDomain){ // Use the constant } 

常量符号也可以在运行时使用dlsym查找。 以这种方式使用否定运算符将不起作用。 您必须根据NULL地址检查常量的地址。

我已经提供了一个非常简单的应用程序示例,该应用程序正在使用一个静态库,该库在GitHub上针对Core Location进行弱链接。 示例应用程序不会链接到Core Location:

TestApp

但是依赖关系可以作为一个可选的(弱)框架:

可选框架

您可以将任何使用CoreLocation框架的代码和导入包装进去

 #ifdef __CORELOCATION__ ... do stuff #endif 

当编译时框架没有被链接时,这将取消所有的CoreLocation代码