我正在努力研究一个混合的Swift和ObjectiveC项目而没有运气 .
我的项目由6个目标组成:
-
App
-
核心
-
CoreTest
-
摘要
-
WatchKit扩展
-
WatchKit App
我已经能够添加一个具有一个目标成员资格(App)的Swift类,并使用从 App-Bridging-Header.h 传递的ObjectiveC代码 . "ObjectiveC into Swift code"范例就像一个魅力 .
相反,我正在努力解决“Swift into ObjectiveC code”范式 . 在特定情况下,我需要在ObjectiveC .m文件中使用一个新的Swift类,该文件是四个目标的成员 .
到目前为止我一直在做的是:
-
将新的Swift文件添加到Core项目,指定四个成员资格(App,Core,Summary,WatchKit Ext)
-
XCode要求为三个项目创建 -Bridging-Header.h Core,Summary和WatchKit Ext(App-Bridging-Header.h已经存在,因为之前已经使用过),我同意(不知道为什么它会在同一个组文件夹中创建这些文件)在哪里我添加我的Swift类,但没关系)
-
我在 class 之前创建了添加 @objc 键的Swift类
-
我去检查是否为所有模块设置了 Objective-C Generated Interface Header Name ,是的
-
我去检查所有模块中 Defines Module 是否设置为 No 并在主项目中设置为 Yes ,是的是
-
我写下了所有四个目标的 -Swift.h 文件的导入
-
在我的Objective-C类中我尝试使用我的新Swift类,显然它似乎工作(甚至自动完成)
-
我尝试构建项目,但它没有说找不到 -Swift.h 文件
我跟着Mix and Match guide of Apple和许多SO线程,包括this one,似乎显然是为了解决我的同样问题,但它不起作用 .
还尝试过删除派生数据以及多次清理整个项目而没有运气 .
EDIT 1 : More details
这是我的Swift类导入RealmSwift的声明
@objc class MyClass: Object {}
这是在ObjectiveC中使用Swift类的片段
MyClass *app = [[MyClass alloc] init];
如果我避免使用#import ...- Swift.h,则构建失败,说我正在使用未声明的标识符“MyClass”,这是合理的 .
如果我使用#import ...- Swift.h文件,它说模块X找不到模块Y,依此类推 .
EDIT 2 : Swift module name
通过查看每个目标的 SWIFT_OBJC_INTERFACE_HEADER_NAME 属性,我看到它是使用这种语法构建的 $(SWIFT_MODULE_NAME)-Swift.h 我是否需要将 SWIFT_MODULE_NAME 更改为 MODULE_NAME ?
EDIT 3 : Imports
这是.m ObjectiveC文件中Swift头的导入集 . 我正在使用相对Build Settings属性中指定的模块名称 . 请注意,由于WatchKit Extension目标在目标名称中有空格,因此其中包含'_'字符 .
#import "ProjectName_App-Swift.h"
#import "ProjectName_Core-Swift.h"
#import "ProjectName_Summary-Swift.h"
#import "ProjectName_WatchKit_Extension-Swift.h"
EDIT 4 : Cross visibility of -Swift.h files
我尝试过以下方法:
-
仅在目标应用程序中添加了Swift类
-
XCode创建了桥接 Headers
-
在仅由App使用的ObjectiveC文件中插入了#import "ProjectName_App-Swift.h"
-
在此文件中使用了Swift类
-
编译!我可以使用Swift类
当为多个目标定义Swift类并且这些多个目标使用ObjectiveC文件时,它不起作用 . 构建错误是这样的:目标X - >“ProjectName_TargetY-Swift.h”文件未找到 . 好像目标无法看到其他目标-Swift.h文件 .
我究竟做错了什么?谢谢你的帮助
6 回答
我在编辑4中做出的假设证明是正确的 . 如果项目有多个目标,则无法在一个.m ObjectiveC文件中导入“-Swift.h”文件 .
因此,必须采用一种解决方案,即更改 SWIFT_OBJC_INTERFACE_HEADER_NAME 构建设置并使其在不同目标中保持相同 . 为此,请将生成此属性的指令从 $(SWIFT_MODULE_NAME)-Swift.h 更改为 $(PROJECT_NAME)-Swift.h ,如here所述 .
按Alt键进入产品菜单后执行此清理构建文件夹 . 由于 Headers 的名称现在在目标之间共享,因此可以在.m ObjectiveC文件中导入一次,并且所有目标都可以从Swift类中受益 .
如果在构建之后仍然显示错误,请确保通过Cmd单击其名称可以从XCode到达标头 . 它应该打开一个包含类似于此代码的文件:
如果需要确保生成这些标头,请打开终端并使用此命令
您应该看到每个目标的一个 Headers
在这些更改之后发生在我身上的另一个问题是它开始在我没有触及的ObjectiveC代码上给出错误 . 问题是由于导入的位置,正如报告here:
在最后,代码编译并在设备和模拟器上运行!
我的解决方案是通过
<>
语法导入生成的swift头:这不是问题的解决方案,但由于很多人可能会在这个页面上找到找不到
<ModuleName>-Swift.h
文件的问题(就像我一样),我想补充一个可能的原因:当swift文件中存在编译器问题时,Xcode可能无法生成标头,因此文件丢失 .
至少在我的情况下,一旦我修复了Swift文件中的编译错误,
<ModuleName>-Swift.h not found
就消失了 .我有类似的问题,几乎最终花了一整天来解决问题,同时遵循其他开发人员关于StackOverflow和其他一些来源的建议 .
我正在从Xcode 7.3.1升级到Xcode 8.2.1和Swift 2.2升级到Swift 3.0.1 .
在我的情况下,我发现
PROJECT_NAME-Swift.h
文件没有在以下位置创建:~/Library/Developer/Xcode/DerivedData/PRODUCT-NAME-hdkrxixrxbiorwesffpqvefxsrzl/Build/Intermediates/PRODUCT-NAME.build/Debug/PRODUCT-NAME.build/Objects-normal/x86_64/PRODUCT-NAME-Swift.h.
我想它不知何故试图从上面的路径引用这个头文件,因此错误 . 我手动复制了它 . 在此之后没有做干净的构建 . 这解决了我的问题,swift头文件开始被创建用于进一步的编译和构建 .
对于我的情况,它在Xcode 8中运行正常,但文件有
如LucioB所描述的那样缺少进口
使用 Xcode 9 删除这些错误
在我的例子中,我有一个工作区,包含一个iOS应用程序子项目,一个框架子项目和一个CocoaPods Pods子项目 . 我的框架子项目中出现“ModuleName-Swift.h文件未找到”错误,因为该文件尚未由Pods子项目创建 .
我不确定是否有办法告诉Xcode子项目之间的依赖关系,但我只是在左侧的Project Navigator中重新排序它们:
beans 荚
框架
iOS应用
之后工作得很好!