我正在try 一个混合了Swift和ObjectiveC的项目,但运气不佳.

我的项目由6个目标组成:

  • 应用程序
  • 果心
  • 果心Test
  • 总结
  • WatchKit扩展
  • WatchKit 应用程序

我已经能够添加一个Swift类,该类有一个目标成员身份(应用程序),并使用从应用程序-Bridging-Header.h个应用程序传递的Objective代码

取而代之的是,我正在与"快速转换为Objective代码"的范例作斗争.

到目前为止,我一直在做的是:

  1. Add a new Swift file to the 果心 project specifying the four memberships (应用程序, 果心, 总结, WatchKit Ext)
  2. XCode asks to create -Bridging-Header.h for three projects 果心, 总结 and WatchKit Ext (应用程序-Bridging-Header.h already exists since it was used previously), and I consent (don't know why it creates those files inside the same group folder where I add my Swift class but nevermind)
  3. 我创建了Swift类,在class之前添加@objc
  4. 我go 判断是否所有模块都设置了Objective-C Generated Interface Header Name,是的
  5. 我go 判断是否所有模块中的Defines Module都设置为No,主项目中的设置为Yes,是的
  6. 我写下所有四个目标的-Swift.h个文件的导入
  7. 在我的Objective-C类中,我try 使用我的新Swift类,显然它似乎有效(甚至自动完成)
  8. 我试图构建该项目,但失败的原因是找不到-Swift.h文件

我已经遵循了Mix and Match guide of 应用程序le多个线程,包括this one,似乎解决了我的同一个问题,但它不起作用.

也看过thisthis,但都不管用.

他们还try 删除派生数据,并多次清理整个项目,但都没有成功.

EDIT 1 : More details

这是我的Swift课程的宣言

@objc class MyClass: Object {}

这是Objective中Swift类的用法片段

MyClass *app = [[MyClass alloc] init];

如果我避免使用#导入-敏捷的h构建失败,说我正在使用未声明的idenfier"MyClass",这是正确的.

如果我使用#导入-敏捷的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

这是中Swift标题的导入集.m ObjectiveC文件.

#import "ProjectName_应用程序-Swift.h"
#import "ProjectName_果心-Swift.h"
#import "ProjectName_总结-Swift.h"
#import "ProjectName_WatchKit_Extension-Swift.h"

EDIT 4 : Cross visibility of -Swift.h files

我try 了以下几点:

  • Added a Swift class only in target 应用程序
  • XCode创建了桥接头
  • Inserted #import "ProjectName_应用程序-Swift.h" in ObjectiveC file used only by 应用程序
  • 在这个文件中使用了Swift类
  • 它编译!而且我能使用Swift类

When the Swift class is defined for multiple targets and ObjectiveC file is used by those multiple targets it doesn't work. The build errors are like this: Target X -> "ProjectName_TargetY-Swift.h" file not found. Seems like a target cannot see other targets -Swift.h files.

我做错了什么?

推荐答案

我在编辑4中所做的假设结果是正确的.

因此,必须采用一种解决方案,那就是更改SWIFT_OBJC_INTERFACE_HEADER_NAME构建设置,并使其在不同目标之间保持一致.

也可以在Build Settings(构建设置)中将Product Module Name(产品模块名称)设置为跨模块相同(我将其设置为$(PROJECT_Name)),以便-Swift.生成的h文件在所有模块中具有相同的名称.这样就不需要添加/判断预处理器宏.

完成此操作后,按Alt键并进入"产品"菜单,即可清理构建文件夹.由于标头的名称在目标之间共享,现在可以在目标中导入一次.m Objective文件和所有目标都可以从Swift类中受益.

如果构建后仍然显示错误,请确保可以通过Cmd单击其名称从XCode访问标题.它应该打开一个包含类似以下代码的文件:

SWIFT_CLASS("_TtC27ProjectName_Summary11MyClass")
@interface MyClass : NSObject
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

如果需要确保生成这些标题,请打开终端并使用此命令

find ~/Library/Developer/Xcode/DerivedData -name "*Swift.h"

你应该看到每个目标都有一个标题

在这些更改之后发生在我身上的另一个问题是,它开始在Objective代码上给出错误,而我并没有触及这些错误.问题是由于进口商品的状况造成的,如报告here所述:

确切地说是在一个房间的顶部.m文件导入隐藏的桥接头可能会有所不同.问题的常见迹象是,出现了"未知类型名"编译错误,其中未知类型是在Objective-C中声明的类.解决方案是#导入.在导入隐藏的桥接头之前,包含Objective-C文件中未知类型声明的h文件.必须这样做可能会令人烦恼,尤其是当所讨论的Objective-C文件不需要了解这个类,但它解决了这个问题并允许编译继续进行时.

最后,代码在设备和模拟器上编译和运行!

Swift相关问答推荐

如何在一个角色隔离类上编写自定义==实现?

如何访问用户选定目录下的(只读)文件?

如何使用Swift宏向 struct 体及其init函数添加新成员?

不能将符合协议的SWIFT类的实例分配给需要该协议的Objective-C属性

如何在 Vapor 中制作可选的查询过滤器

Observable.create 捕获行为

memcpy 复制带偏移量的数组

SwiftUI:按钮的圆形边缘的边框尺寸加倍

如何裁剪图像 3:4 ?迅速

如何为 Swift UI 视图定义 struct ?

Swift 全局函数列表

Swift 非参与者隔离闭包

与 SwiftUI 中的 onChange 修饰符相比,objectWillChangeSequence 的目的是什么?

来自数据的 SwiftUI 图像

更改该函数的参数之一时,如何将这些 SwiftUI 异步任务合并到一个任务中以从函数中获得正确的结果

如何仅将 SwiftUI 不透明度应用于父视图?

Swift:连接两个数组而不重复共享后缀/前缀

AVPlayer 在 iOS 15.4 中寻求 completionHandler 返回 false

如何在 GCD 中停止 DispatchWorkItem?

如何发送静默推送通知有效负载