Xcode 6 / Beta 4:使用桥接头文件与框架目标不受支持。

146
我刚刚升级到 Xcode 6 Beta 4,并有一个在 Beta 2 中为实时视图创建的框架。由于另一个 Swift bug,我需要使用一些 Obj-C 代码。然而,在升级时,我遇到了以下错误:
错误:不支持使用框架目标的桥接标头
我没有在发行说明中看到任何信息,也没有找到其他迁移路径。有人遇到过这个问题并找到了解决方案吗?
我知道 Beta 3 消除了实时视图的框架需求,但如果可以让它正常工作,对我来说是有意义的。如果在 Beta 4 中它们不是完全失效的话,我可以删除它作为备选方案,但更喜欢使用框架。

我意识到Beta 3消除了框架的需求。怎么做到的? - hnh
2
(用于实时视图) - Chris Conover
1
我遇到了同样的问题。 - Simon Germain
2
哇,你的小修改让我的生活变得更美好了 - 我从没听说过这个改变(消除框架的需求),我一直在为实时视图的框架目标苦苦挣扎了几个小时。非常感谢你,@chrisco! - yonix
4个回答

260

正如错误所述,桥接头文件不允许在框架中使用。苹果的Mix & Match开发文档中的“从同一框架目标内导入代码”部分提到了这一点。正如他们所说,您需要“在您的总头文件中导入每个您想要暴露给 Swift 的 Objective-C header”。

然而,我发现您可能还需要将那些特定的头文件设置为公开。本答案回顾了为什么需要这样做以及如何操作:Swift 编译器错误:“非模块化的框架模块内的头文件”

因此,请执行以下操作:

  1. 删除桥接头文件。
  2. 从框架的构建设置中删除对桥接头文件的引用
  3. 在您的总头文件([ProductName].h)中添加必需的头文件。
  4. 在框架的“生成阶段”中的“头文件”部分将包含的文件设置为公开。
  5. 清理并重新构建。

注意:“总头文件”是一个文件(通常命名为[ProductName].h),它代表了一个框架的所有公共头文件。它通常只是一个列出了包含在框架中的其他头文件的 #import 语句列表。在 Xcode 中,如果您打开 UIKit.h,则会看到一个很好的总头文件示例。


3
感谢您简洁明了的回答(标记为如此)。我已经阅读了那一节,但是对Umbrella和Bridging header之间的区别感到困惑。 - Chris Conover
1
@zaxy78,请查看此文档中的“将 Swift 导入 Objective-C”部分:https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_77 - DeepFriedTwinkie
4
@DeepFriedTwinkie,当您说“将必要的头文件添加到您的Umbrella文件中”时,您指的是哪个Umbrella文件?谢谢。 - Allan Macatingrao
2
这正是我所需要的。将它们添加到公共部分就可以解决了。 - olivaresF
25
那么,我是否可以这样理解:我希望在我的框架中保持私有的任何类,如果必须被Swift类使用,那么现在必须对任何使用我的框架的人公开。这似乎不是一个理想的解决方案。 - ospr
显示剩余14条评论

39

有两种可能性。将必要的头文件加入到umbrella头文件中并使它们公开是一种方法。但是,如果这些头文件应该对Swift可用,但不应该公开,则会出现问题。

第二种可能性是详细描述如何让内部头文件对Swift可用,可以在这里找到。基本上需要创建一个类似以下的模块映射:

module AwesomeKitPrivate {  
  header "../InternalClass.h"
  export *
}

可以使用以下设置将其包含在XCode中:

SWIFT_INCLUDE_PATHS = $(SRCROOT)/AwesomeKit/ProjectModule  

4
太好了!谢谢。比起将所有标题都公开,这种技术更受欢迎。 - David H
强烈建议使用该解决方案,同时查看提供的链接以获取详细解决方案。 - Tancrede Chazallet
这是我认为的正确答案,但根据您想要实现的目标,您可能可以使用一些由苹果提供的宏来帮助Swift-Objc互操作性:https://developer.apple.com/documentation/swift/objective-c_and_c_code_customization - Joe Susnick
1
header语句接受相对路径。当您想要添加另一个框架的头文件时,该怎么办? - Georgios
@Georgios回退到使用umbrella-header方法(如果从另一个框架导入公共头文件,则不要使用此方法) - Top-Master

15

请参见将Objective-C导入Swift

要从相同的框架中将Objective-C代码导入Swift,请执行以下操作:

  1. 在“Build Settings”下的“Packaging”中,确保该框架目标的“Defines Module”设置为“Yes”。
  2. 在您的伞头文件中,导入您想要向Swift公开的每个Objective-C头文件。例如:

        #import "XYZ/XYZCustomCell.h"
        #import "XYZ/XYZCustomView.h"
        #import "XYZ/XYZCustomViewController.h"
    
  3. 在该框架的“构建阶段”中的“Headers”部分中公开包含的文件。

  4. 清理并重新构建。

Swift将查看您在伞头文件中公开的所有标头。该框架中Objective-C文件的内容将自动在该框架目标内的任何Swift文件中可用,无需任何导入语句。使用与系统类相同的Swift语法使用自定义Objective-C代码。

let myOtherCell = XYZCustomCell()
myOtherCell.subtitle = "Another custom cell"

重要提示: "伞形头文件" 指的是文件 {ModuleName}.h。顺便提一下,目标名称为 {ModuleName}.framework。


2
我想在我的模块Swift文件中使用objc文件,但我不想将它们暴露给其他模块。我该如何做? - Sazzad Hissain Khan
嗨,@SazzadHissainKhan,你解决问题了吗?我也在努力解决同样的问题。我想让我的Objective-C头文件对Swift可见,但不暴露给外部世界。 - Ivan
@Ivan,我真的记不清我当时做了什么。希望这个问题已经在后来的Swift版本中得到解决。 - Sazzad Hissain Khan

1
在我的情况下,只需从我的框架的“构建设置”中删除“Objective-C Bridging Header”设置即可解决问题。

enter image description here


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