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

6

我正在构建自己的框架,旨在分发给其他开发人员以包含到他们的项目中。该框架可选地链接某些框架(例如CoreLocation)。问题在于,当我将我的框架链接到不包含Build Phases中的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包含到他们的项目中?实际上,我知道这是可能的,但我应该怎么做才能实现呢?

2个回答

11

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

您需要解决两个问题:类可用性和符号可用性。苹果在框架编程指南:框架和弱链接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

但是这个依赖项作为一个可选的(弱)框架存在:

optional framework


编译主项目时,这并不能避免链接器错误。 - heximal
@heximal,看一下我链接的项目。 - quellish
非常感谢您花时间来帮助我,但是CoreLocation已经链接到TestApp项目中了。我的目标是避免这种情况。我知道,有办法可以做到这一点。 - heximal
@heximal 在那个项目中有所展示。请查看 Biblioteque.m。 - quellish
是的,我看到了。它演示了kCLErrorDomain常量的强制转换,该常量被声明为NSString,这是指针类型。我需要的kCLDistanceFilterNone是原始的double类型。我不明白如何将dlsym方法应用于此(我很抱歉,我知道)。 - heximal
显示剩余3条评论

1
您可以将使用CoreLocation框架的任何代码和导入语句包装在一个 #if 块中,以确保只有在可用时才会编译和链接此代码。
#ifdef __CORELOCATION__
... do stuff
#endif

这将在编译时未链接框架时,使所有CoreLocation代码无效化。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接