6

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

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 包含在他们的项目中?实际上,我知道这是可能的,但我应该怎么做才能做到这一点?

4

2 回答 2

11

根据您对问题的描述,我假设您已经知道如何通过将 Xcode设置为“可选”来使 Xcode 与框架进行弱链接。

您有两个问题需要解决:类可用性和符号可用性。Apple 在Framework Programming Guide: Frameworks and Weak LinkingSDK Compatibility Guide: Using SDK Based Development中对此进行了介绍

课程可用性

这非常简单:用于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 上的核心位置进行了弱链接。 示例应用程序未链接到核心位置:

测试应用

但是依赖项确实是一个可选(弱)框架:

可选框架

于 2014-09-02T20:32:52.627 回答
1

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

#ifdef __CORELOCATION__
... do stuff
#endif

当在编译时未链接框架时,这将否定所有 CoreLocation 代码

于 2014-09-03T12:55:35.493 回答