现在我想把我的ObjC框架迁移到Swift,我得到了以下错误:

include of non-modular header inside framework module 'SOGraphDB'

引用是一个头文件,它只是定义了一个协议,我在一些类中使用这个头文件来使用这个协议。

这似乎与模块特性有关,但目前不太清楚如何修复,你知道解决方案吗?

更新:

这是一个Swift编译器错误。

更新2:

一个快速的解决方法(但不能解决根本原因)是将以下设置设置为yes: clang_allow_non_modular_incles_in_framework_modules = yes


当前回答

我也想补充一下我在这个问题上的经验。

总结一下:

@ambientlight的回答很棒,它解决了大部分问题。 允许非模块化报头是另一种解决方案(参见上面的一些答案)。 将框架的头标记为公共的(只有那些您想要公开的),并将它们导入到伞形头中。

以下是我对上述答案的2个补充:

carefully check the imports in your project for headers which import your frameworks directly in them (instead of using forward declaration, if possible) -- it is not a good practice to include a header file inside another header file; sometimes this causes a problems, because if not done properly this may lead to multiple include-ing of one header and create linker issues. UPDATE: make sure that the architectures of the library and that of the target that you want to link it to match. and lastly, after doing all of the above, I still kept bumping onto that error. So I dug a little more and found (in the apple developer forums, but I lost the link :( ) that if you include the headers in the umbrella header not like this <framework/headerName.h>, but only like this "headerName.h", the problem goes away.

我尝试了最后一个,到目前为止我还没有遇到过这个问题,但是我怀疑这个解决方案只有在你应用了一些顶部的答案时才有效(注意:它们并不都相互兼容,例如,模块方法和允许非模块头包含)。

其他回答

我解决了它从框架中删除模块文件夹。

使用finder浏览到应用程序项目中显示的框架位置 进入Test.framework文件夹(在上面的例子中,它将是SOGraphDB.framework) &删除模块文件夹。 清洁和重新构建应用程序,它将解决问题。

头文件已分配给目标,但仅被标记为项目可见,只是更改为公共导致解决此错误。

这是编译器预期的行为,有很好的理由。

I think the majority of people running into this issues is caused after they switch from Application Target to Framework Target and start adding C and Objective C headers into framework's umbrella header expecting it to have a same behaviour as application's Bridging Header, which behaves differently. The umbrella header is actually designated for mixed swift, obj-c framework and its purpose is exposing the APIs to the outer world that your framework has in objective-c or c. That means the headers we put there should be in the public scope.

它不应该被用作将不属于框架的Objective-C/C头文件暴露给框架swift代码的地方。因为在这种情况下,这些头文件也将作为框架模块的一部分对外公开,这通常不是我们想要做的,因为它破坏了模块化。(这就是为什么允许非模块化包含在框架模块默认为NO)

为了将Objective-C/C库公开给你的框架swift代码,我们应该为这个库定义一个单独的swift模块。然后可以使用标准的快速导入YourLegacyLibrary。

让我在一些典型场景中演示这一点:将libxml2嵌入到我们的框架中。

1. 首先需要创建一个模块。Modulemap文件,如下所示:

对于OSX框架:

module SwiftLibXML2 [system] {
  header "/usr/include/libxml2/libxml/xpath.h"
  export *
}

对于iOS框架:

module SwiftLibXML2 [system] {
  header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/xpath.h"
  export *
}

它所做的只是将头文件和它在swift模块中引用的其他头文件打包起来,这样swift就能够为这些C接口生成swift绑定。

2. 然后在你的xcode项目目录中创建一个文件夹SwiftLibXML2,并把这个模块。modulemap那里

3.在构建设置中,将$(SDKROOT)/usr/include/libxml2添加到头搜索路径中

4. 在Build Settings中,将$(SRCROOT)/SwiftLibXML2添加到Import Paths中

5. 在Project的General选项卡下,添加libxml2。tbd到链接的框架和库。

现在你可以在需要的地方导入这个模块:

import SwiftLibXML2

(如果你想看一个更完整的模块。地图的例子,我建议参考达尔文的模块。模块映射在/usr/include/module。modulemap,你需要安装Xcode命令行工具才能到达那里,参考OS X El Capitan中缺少/usr/include)

我在将一个项目从swift2更新到swift3后遇到了这个问题。我使用XCode 8.3.2更新代码,无法摆脱“框架模块内的非模块化头”的错误。当我在另一个版本的XCode(版本9.0.1)中打开相同的项目时,错误没有出现。

对我来说,解决方案是去目标->构建设置->允许框架模块中的非模块化包含切换到YES!