Swift编译器错误:"框架模块内部的非模块化头"

Ste*_*han 200 frameworks objective-c swift

现在我想将我的ObjC框架迁移到Swift,我收到以下错误:

include of non-modular header inside framework module 'SOGraphDB'
Run Code Online (Sandbox Code Playgroud)

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

似乎与模块功能有关,但目前还不太清楚如何修复,你知道一个解决方案吗?

更新:

这是一个Swift编译器错误.

更新2:

快速修复(但不解决根本原因)是将以下设置设置为yes:CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES

kgr*_*nek 307

你的标题是公开的吗?

在项目资源管理器中选择头文件.然后在xcode右侧的部分中,您会注意到目标旁边有一个下拉列表.将其从"项目"更改为"公共".这对我有用.

公共标题

  • 您还可以进入框架的标头构建阶段,快速查看哪些标头是公共的、项目的和私有的。 (2认同)
  • 如果我*希望*这些标头是内部的怎么办? (2认同)
  • 这也解决了我的问题!在我的情况下,由于模块化问题,我的一个依赖于另一个pod的pod无法导入它.所以我使用公共模式将一些标题包含在另一个pod的目标中.它解决了这个问题! (2认同)

amb*_*ght 130

这是一种预期的编译器行为,并且有很好的理由.

我认为大多数遇到这个问题的人是在他们切换Application TargetFramework Target并开始将C和Objective C头添加到框架的伞头之后引起的,期望它具有与应用程序的桥接头相同的行为,其行为不同.实际上,伞标题被指定用于混合swift,obj-c框架,其目的是将API暴露给您的框架在objective-c或c中具有的外部世界.这意味着我们放在那里的标题应该在公共范围内.

它不应该用作将框架中不包含的Objective-C/C头部暴露给框架的快速代码的地方.因为在这种情况下,这些头文件也将作为我们框架模块的一部分暴露给外部世界,这通常不是我们想要做的,因为它打破了模块化.(这正是为什么允许框架模块中的非模块化包含默认为NO)

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

让我在一些典型场景中证明这一点:嵌入libxml2到我们的框架中.

1.首先需要创建一个module.modulemap以这种方式显示的文件:

对于OSX框架:

module SwiftLibXML2 [system] {
  header "/usr/include/libxml2/libxml/xpath.h"
  export *
}
Run Code Online (Sandbox Code Playgroud)

对于iOS框架:

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

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

2.然后在你的xcode项目目录中创建一个文件夹SwiftLibXML2并将此module.modulemap放在那里

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

4.在" 构建设置"中,添加$(SRCROOT)/SwiftLibXML2到" 导入路径"

5.在项目的常规选项卡下,添加libxml2.tbd链接的框架和库.

现在,您可以根据需要导入此模块:

import SwiftLibXML2
Run Code Online (Sandbox Code Playgroud)

(如果你想看起来更完整module.map例如,我会建议在引用达尔文的module.modulemap /usr/include/module.modulemap,你需要安装的Xcode命令行工具去那里,参考缺少/ usr/include目录在OS X埃尔卡皮坦)

  • 文件名 `module.map` 已弃用,应重命名为 `module.modulemap` http://clang.llvm.org/docs/Modules.html#attributes (2认同)

fun*_*oll 55

以下是自动应用快速修复的方法,因此您无需Pods.xcodeproj在每次修改后手动更改pod install.

将此代码段添加到Podfile的末尾:

post_install do |installer|
  installer.pods_project.build_configuration_list.build_configurations.each do |configuration|
    configuration.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
  end
end
Run Code Online (Sandbox Code Playgroud)


小智 29

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

  • 我已经完成了这一步......它工作了一段时间......现在它无法运行......我也包括了pod-install步骤.但它现在又失败了.还有什么我应该检查的吗?我没有将GoogleMobileAds.Framework视为将标头更改为Public的选项. (3认同)

Jim*_*Dee 15

我想我绕过了这个.我有一些在框架中使用sqlite3的模型代码.就我而言,罪魁祸首是<sqlite3.h>.

问题是在我的Module/Module.h头文件中,我导入了导入<sqlite3.h>的公共头文件.解决方案是隐藏所有sqlite3_xxx类型,并确保它们在任何公共.h中都不可见.所有对sqlite3的直接引用都是私有或项目可见性.例如,我有一个公共单例,它有一些sqlite3_stmt指针挂在它上面.我把它们移到了一个单独的类中,现在只是该公共头中的前向声明.现在我可以建立.

顺便提一下,CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES设置不起作用.我尝试在框架和依赖项目中设置它.这种解决方法是必要的,但我不确定为什么.

  • 当我尝试在我的框架模块中包含SSZipArchive时,我很确定这是我的问题的解决方案.公共标题正在冒充<zlib.h>并给出相同的错误.你可以在某个地方发布你的源代码,因为我很难让它工作,因为我只理解你的部分答案..谢谢! (4认同)

Kin*_*ard 15

Swift中:

1.修改您的Xcode项目并定位'Build Settings,如下所述:

允许框架模块中的非模块化包含:否

启用Bitcode:是的

2.使用适用于GoogleMaps iOS SDK的最新版本(使用CocoaPods获取它):

GoogleMaps(1.10.4)

3.评论有问题的导入:

//import GoogleMaps
Run Code Online (Sandbox Code Playgroud)

4.创建或修改桥接头文件,添加有问题的导入:

[您的Xcode项目名称] -Bridging-Header.h

// Use this file to import your target's public headers 
// that you would like to expose to Swift.
#import <GoogleMaps/GoogleMaps.h>
Run Code Online (Sandbox Code Playgroud)

5.清理并重新构建Xcode项目.


hfo*_*sli 7

#import "MyOtherFramework.h"
Run Code Online (Sandbox Code Playgroud)

#import <MyOtherFramework/MyOtherFramework.h>
Run Code Online (Sandbox Code Playgroud)


seo*_*seo 6

这个答案已经过时了.

导入框架时,必须导入与根标头共享依赖关系的所有头文件.确保这一切始终有效的最简单方法是将框架的"Headers"文件夹中的所有标头导入到公共标头路径中.

在此输入图像描述

Swift编译器使用此信息生成非损坏符号的映射及其关联的类型信息.