我的应用程序单元在模拟器中运行时测试构建和测试,但在构建和测试设备时失败并出现链接器错误。
在我的应用程序目标上,我设置了以下构建设置:
DEPLOYMENT_POSTPROCESSING = NO
GCC_SYMBOLS_PRIVATE_EXTERN = NO
在我的单元测试中,我设置了以下构建设置:
BUNDLE_LOADER = $(BUILT_PRODUCTS_DIR)/<app name>.app/<app>
TEST_HOST = $(BUNDLE_LOADER)
链接器错误是:
Undefined symbols for architecture armv7s:
"_<An NSString * const>", referenced from:
-[UnitTestClassA setUp] in UnitTestClassA.o
"_<Another NSString * const>", referenced from:
-[UnitTestClassB helperMethod:] in UnitTestClassB.o
-[UnitTestClassB anotherHelperMethod:] in UnitTestClassB.o
ld: symbol(s) not found for architecture armv7s
clang: error: linker command failed with exit code 1 (use -v to see invocation)
...我在Xcode的首选项中打开了“在构建错误后继续”,但是我没有收到大量的抱怨NSString * const的链接器错误。如果我做错了什么,那么由于我在整个生产代码中使用字符串常量,因此我会得到比我少数人更多的链接错误。
我正在创建我的字符串常量:
.h档案......
extern NSString * const ReallyGoodString;
.m文件......
NSString * const ReallyGoodString = @"This string is great!";
... .m文件是生产代码,也是我的应用程序目标的一部分,因此我不必将其链接到单元测试包中。
那么,这里发生了什么?为什么这在模拟器中工作得很好而不在设备上?
我发布了sample project to Github来说明问题。您可以在示例项目中看到此问题不一致:某些符号链接很好,其他符号则没有。
答案 0 :(得分:27)
当链接器创建Linker-Error
可执行文件时,它会丢弃FHKViewControllerThisSymbolWontLink
,因为可执行文件中没有任何内容使用它。链接器不知道它应该保持单元测试包(在运行时动态加载)使用的符号。
您可以告诉链接器不要通过使用used
属性标记它来剥离未使用的符号,如下所示:
NSString * const FHKViewControllerThisSymbolWontLink __attribute__((used)) = @"name";
您需要为您定义的每个符号执行此操作,该符号未被主可执行文件使用但由测试套件使用。
答案 1 :(得分:12)
这很可能是因为您的测试套件正在使用主要应用程序未使用的符号,并且启用了死代码剥离。您可以在每个配置的基础上禁用死代码剥离选项。我修复了一个类似的问题,通过将选项翻转到 No 仅用于Debug版本,使测试能够在我的设备上运行。
答案 2 :(得分:1)
一些可能性:
您导入标题但不链接正确的库。这很常见,特别是对于像QuartzCore这样的库的头文件,因为默认情况下它不包含在项目中。要解决:
一个。在Build Phases的Link Binary With Libraries部分添加正确的库。
您将文件复制到项目中但忘记检查要添加文件的目标。要解决:
一个。打开正确目标的Build Phases,展开Compile Sources并添加缺少的.m文件。
如果您使用的是逻辑测试,则iOS设备不支持它们,但仅限于模拟器。应用程序测试虽然适用于设备。文件:
iOS:虽然Xcode可以运行逻辑和应用程序单元测试 模拟器,Xcode无法在iOS设备上运行逻辑单元测试。 因此,如果您包含并激活了两种类型的单元测试 一个方案,你将无法使用该方案来运行单元测试 iOS设备。
答案 3 :(得分:0)
我曾遇到类似的问题,解决方案就像清理项目一样简单,我想你已经尝试过了,但也许没有。我至少试一试。只需转到“产品” - &gt;顶部导航栏中的“清理”,或使用快捷方式:“shift”“command”“K”
(我会把它写成评论而不是答案,因为它不仅仅是一个简单的建议。但我没有足够的评论,抱歉)。