使用多个目标的Objective C到Swift头文件

83
我已经成功通过导入语句从Objective C中的'Swift'类(针对目标应用程序'MyApp')中调用它们。
结果为:

我已经成功通过导入语句从Objective C中的'Swift'类(针对目标应用程序'MyApp')中调用它们。

#import "MyApp-Swift.h"

我现在创建了一个名为"MyAppLite"的新目标。

当我编译新目标时,会出现错误,因为代码需要 "MyApp-Swift.h",但编译器正在创建 "MyAppLite-Swift.h"

因此,我需要为我正在编译的目标创建一个条件性的Swift/ObjC头文件#import

这可以如何完成,或者有更好的方法吗?

7个回答

97

在构建设置中,还可以将Product Module Name设置为跨模块的相同名称(我将其设置为$(PROJECT_NAME)),以便生成的<project>-Swift.h文件在所有模块中具有相同的名称。这样就不需要添加/检查预处理器宏。


1
当您在项目中创建第一个Swift文件时,Xcode会要求您将桥接标头添加到该项目中。在我的情况下,它只向第一个构建目标添加了所需的配置。因此,我还需要通过配置“Objective-C Bridging Header”来修复其他构建目标。 - Kevin R
我发现这会导致构建过程中出现问题,并且在它们之间切换时,我需要清理构建文件夹。我认为这是因为它们都共享相同的项目名称,它们都构建到同一个文件夹中。 - Saltymule
11
我不确定,但我的感觉是,如果搞乱了“产品模块名称”,可能会在以后的某个时候影响到某些东西,可能是在提交到应用商店时;而根据其他答案所述更改“Objective-C生成的接口头文件名称”则没有任何影响。 - Dan Rosenstark
2
@Yar 刚看到你的评论。一开始我也有同样的感觉,但是这个应用程序已经在应用商店上一段时间了,而且并没有出现问题。但是如果我正在使用最新版本的 Xcode,我会使用 Mike Fay 的解决方案。这个答案是在 SWIFT_MODULE_NAME 可用之前做出的。 - C0D3LIC1OU5
这并不是正确的答案,我会选择第二个最受欢迎的答案。 - Sam Furlong
显示剩余2条评论

68
我发现解决这个问题最好的方法是在您的Xcode共享项目设置中进行。您可以搜索以下设置:

Objective-C生成接口头文件名*

如果将该值设置为公共“头文件名称”,例如“MyProject-Swift.h”,它将应用于每个目标,并且您可以在任何Objective-C文件中安全地使用导入声明。如果需要,这允许您继续为每个目标使用唯一的产品模块名称。
我已在Xcode Version 6.4 (6E35b)中测试过此方法。
*注意:这将出现在Swift编译器设置下,仅当您向项目添加了Swift源文件时才可见。此外,如果目标没有与之关联的Swift源,则该目标的构建设置中将不会显示Swift编译器选项。
祝您好运!

4
在我看来,这是最好的解决方案。 - Rafael Nobre
2
这个的原始值是 $(SWIFT_MODULE_NAME)-Swift.h... 所以虽然这个答案很棒,但我非常想知道如何调整模块的 SWIFT_MODULE_NAME - Dan Rosenstark
1
在这里,我建议使用一些明显的名称来减少混淆,例如MidiDesignerAllTargets-Swift.h。感谢您提供这个很棒的答案,真是太好了。 - Dan Rosenstark
1
如果您正在使用Xcode 7+,那么这是最佳解决方案。 - hdoria
1
它在8.3.3(8E3004b)版本中肯定仍然可用。 - Mike Fay
1
@AntonTropashko 你需要选择显示/筛选“全部”而不是“基本”才能看到它。 - CyberMew

52

前面的回答存在一些问题,如果您决定重命名目标或项目,或者按照预期使用SWIFT_MODULE_NAME,则会出现问题。

最通用的解决方法是在项目的而不是目标的构建设置下更改SWIFT_OBJC_INTERFACE_HEADER_NAME(“Objective-C生成的接口头文件名称”),分别为:

  • $(PROJECT_NAME)-Swift.h — 每个项目一个;
  • $(SWIFT_MODULE_NAME)-Swift.h — 每个模块一个(默认值)。

输入图像描述


2
最干净的解决方案。Xcode 8.3.3,Swift 3,请确保共享的 Swift 文件属于每个目标,这样所有的工作都会在此之后完成。 - Klajd Deda
1
如何处理类似警告的 "$(PROJECT_NAME)-Swift.h file not found" 错误? - ViruMax
1
这应该被接受为答案,因为它展示了更多的细节,尽管@C0D3LIC1OU5的答案已经足够好了。 - Sandeep Rana
1
这就是我想要的。谢谢你的回答。 - Emre Önder

6

嗯,我唯一能解决的方法就是...

#ifdef IS_LITE
#import "MyApp_Lite-Swift.h"
#else
#import "MyApp-Swift.h"
#endif

请注意,如果我的产品模块名称中有任何“非法”字符,它们需要被替换为下划线。
希望这能帮到你!

这对我有效,因为接受的答案在切换目标时会导致构建问题。 - Saltymule
什么是IS_LITE? - Duyen Hang Kim

5
我在前缀头文件(-Prefix.pch)中放置了适当的 #import -Swift.h 语句,为每个构建(目标/方案)定义/添加。

这样做的好处是使得在Objective-C中使用Swift类更加方便,并且增强了Swift体验和Objective-C体验之间的一致性,因为Swift中不需要显式导入头文件。 - paulmelnikow

1

pickture会告诉你一切

  1. 第二个目标的名称是xxx和xxx-ih

enter image description here

  1. 选择第一个目标,点击 build setting -> 找到 Objective-C Bridging Header,设置为 xxx-bridging-Header.h,并将 Objective-C Generated Interface Header Name 设置为 xxx-Swift.h enter image description here

  2. 选择第二个目标,同样执行步骤 2 enter image description here


0
唯一有效的方法如下:

1- 从第一个目标(具有工作桥接)的构建设置中选择Objective C Bridging Header
2- 复制Objective C Bridging Header
3- 打开另一个目标的构建设置
4- 粘贴它 5- 将头文件更改为您的新头文件(即target B.h)

(现在您可以为两个目标选择此选项)

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