Foo类同时在MyApp和MyAppTestCase中实现。 将使用两者之一。 哪一个是未定义的

最近我开始unit testing我的应用程序。 这个项目(在Xcode4中)是在没有unit testing包的情况下创build的,所以我不得不进行设置。 我已经按照从这里的步骤: http : //cocoawithlove.com/2009/12/sample-mac-application-with-complete.html而且它对于简单的类很好,但现在我试图testing一个类,取决于在另一个和另一个等等

首先我得到了一个链接器错误,所以我添加了*.m文件到testing用例目标,但现在我得到了每一个类,我试图testing的警告:

Foo类同时在MyApp和MyAppTestCase中实现。 将使用两者之一。 哪一个是未定义的

我不知道为什么呢? 我该如何解决这个问题? 也许我在设置unit testing目标时错过了一些东西?

编辑 – 解决scheme

  • 将“Bu​​ndle Loader”正确设置为$(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • 将“默认隐藏的符号”设置为“ 否” (在目标应用程序的“生成设置”中)。 这是链接器错误来自哪里,因为它默认是YES! 我一直在努力这么久!

来源: unit testing与XCode 4链接错误?

Foo类同时在MyApp和MyAppTestCase中实现。 将使用两者之一。 哪一个是未定义的

我不知道为什么呢?

因为这两个图像(应用程序和unit testing包)定义了类的实现。 该类被dynamic加载到objc运行时。 objc运行时使用一个平面名称空间。 这是如何工作的:

  • 二进制文件被加载,从它的依赖关系开始
  • 当每个二进制文件被加载时,objc类将在objc运行时注册
  • 如果具有特定名称的类被加载两次,则行为是未定义的。 可以将一个类的实现(名称相同)加载到objc运行时。

这里的典型问题是您将返回一个实现 – 当types冲突(当类不是来自同一个源文件时),您的应用程序可能会崩溃。

你通常通过重命名一个类或者在一个图像中导出类来避免这种情况。 重命名类明显不适用于你的情况。 你有一个文件Foo.m正在编译,导出,并加载两个图像,当它应该在一个。

这应该被你解释为一个重复的符号链接器错误。 即使实现是相同的源文件(并且实现是相同的) – 这是您必须解决的问题。

我该如何解决这个问题?

如果Foo.m是应用程序的一个类,则必须从unit testing中删除(不编译和链接) Foo.m 。 如果它是unit testing的一部分,则不要将其编译并链接到unit testing目标中。

然后,按照post中的说明链接/加载你的unit testing到应用程序。 这是在这个职位的一般领域: 其中“WhereIsMyMac”是您正在进行unit testing的应用程序的名称。 这将使testing目标与应用程序链接(所以编译时不会出现链接器错误)。 最重要的部分是你的testing文件被编译到unit testing目标(仅),你的应用程序的类被编译和链接到应用程序。 你不能只是添加他们 – 他们链接和dynamic加载。

也许我在设置unit testing目标时错过了一些东西?

从你链接的文章:

注意:testing目标是一个单独的目标。 这意味着你需要小心目标成员。 所有的应用程序源文件只能添加到应用程序目标中。 testing代码文件只能添加到testing目标。

错误的部分可能是unit testing包的链接和加载阶段。

如果你正在使用Cocoapods,你的podfile只需要主目标部分的依赖关系,而不是testing目标。 如果您为testing目标添加了重复的依赖关系,则会得到OP的错误消息。

 target 'MyProject' do pod 'Parse' end target 'MyProjectTests' do end target 'MyProjectUITests' do end 

对我而言,我所需要做的就是取消选中使Foo类成为unit testing目标成员的checkbox。 它不应该是两个目标的成员,应该是这样的:

目标会员

如果你看不到图像,这是Xcode“目标成员”窗格的屏幕截图。 有两个目标:一个带有“A”应用程序图标和testing名称。 另一个是unit testing目标,并有一个unit testing图标:

 Target Membership [X] Foo [ ] FooTests 

对我来说,这是因为我部署到设备,然后到模拟器,因为我有NSZombies启用。 解决scheme是切换到模拟器configuration和做一个产品 – >清洁然后切换到设备configuration和做同样的。 错误消失了。 这是build立caching。

原因是你重写了其他目标中定义的App Target的构build设置的RUNPATH_SEARCH_PATHS。

解:

转到您的应用目标并findRUNPATH_SEARCH_PATHS构build设置,并在其中使用$(inherited)标志: DebugRelease