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

时间:2014-06-08 05:04:24

标签: objective-c frameworks swift

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

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

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

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

更新:

这是Swift编译器错误。

更新2:

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

20 个答案:

答案 0 :(得分:297)

你的标题是公开的吗?

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

public header

答案 1 :(得分:122)

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

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

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

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

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

1。您首先需要创建一个module.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并将此module.modulemap放在那里

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

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

5. 在项目的常规标签下,将libxml2.tbd添加到关联的框架和库

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

import SwiftLibXML2

(如果你想看一个更完整的module.map示例,我建议在/usr/include/module.modulemap引用Darwin的module.modulemap,你需要安装Xcode命令行工具去那里,引用{{ 3}})

答案 2 :(得分:53)

以下是自动应用快速修复的方法,因此您无需在每个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

答案 3 :(得分:29)

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

答案 4 :(得分:15)

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

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

顺便提一下,CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES设置无效。我尝试在框架和依赖项目中设置它。这种解决方法是必要的,但我不确定原因。

答案 5 :(得分:15)

Swift

<强> 1。修改您的Xcode项目并定位“构建设置”,如下所述:

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

启用Bitcode:是

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

GoogleMaps(1.10.4)

第3。评论有问题的导入:

//import GoogleMaps

<强> 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>

<强> 5。清理并重新构建您的Xcode项目。

答案 6 :(得分:5)

此答案已过时。

导入框架时,必须导入与根标头共享依赖关系的所有标头文件。确保这一切始终有效的最简单方法是导入框架中的所有标题&#34;标题&#34;将文件夹放入公共标题路径。

enter image description here

Swift编译器使用此信息生成非错位符号的映射及其关联的类型信息。

答案 7 :(得分:3)

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

答案 8 :(得分:3)

<强>唐&#39;吨

#import "MyOtherFramework.h"

<强>不要

#import <MyOtherFramework/MyOtherFramework.h>

答案 9 :(得分:2)

我知道这是一个老问题,但我有同样的问题,上面的任何内容都没有帮助我。所以我希望我的回答对某人有帮助。 就我而言,问题出在ALWAYS_SEARCH_USER_PATHS设置中。当它被设置为NO项目建立和工作正常。但就其中一个pod要求将其设置为YES而我收到错误

  

在框架模块中包含非模块化头文件

经过几杯咖啡和一整天的研究,我发现根据Xcode 7.1 Beta 2 release notes的已知问题:

  

•如果您收到错误声明&#34;在框架模块中包含非模块化标头&#34;为一个   以前编译过的框架,确保&#34;始终搜索用户路径&#34;   构建设置设置为&#34;否&#34;。默认为&#34;是&#34;仅用于遗留原因。 (22784786)

我当时正在使用XCode 7.3,但似乎这个bug还没有修复。

答案 10 :(得分:2)

我想补充一下我对这个问题的经验。

总结一下:

  • @ ambientlight的答案很棒,它解决了大部分问题。
  • 允许非模块化标头是另一种解决方案(参见上面的一些答案)。
  • 将框架的标题标记为公开(仅显示您要公开的标题)并将其导入伞标题。

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

  • 仔细检查项目中的导入是否有直接导入框架的标题(如果可能的话,不要使用前向声明) - 在另一个头文件中包含头文件不是一个好习惯。有时这会导致问题,因为如果没有正确完成,可能会导致多个包含一个标头并产生链接器问题。
  • 更新:确保库的体系结构和要链接它的目标的体系结构匹配。
  • 最后,在完成上述所有操作后,我仍然遇到了这个错误。所以我挖了一点并发现(在苹果开发人员论坛中,但我丢失了链接:()如果你在标题中包含标题而不是像<framework/headerName.h>那样,但只有这样{{1}问题消失了。

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

答案 11 :(得分:1)

在项目中包含我自己的框架时,我遇到了这个问题。通过将.m文件中的所有sqlite3.h导入不是公共的.h文件来修复它。我假设其他库可能会标记与Xcode类似的问题。

答案 12 :(得分:1)

我遇到了Facebook 4.02 sdk和FBSDKCoreKit的具体问题。

我做了所有步骤,但仍然是关于非模块化标头的错误。我只拖放框架中的特定标题以构建阶段 - &gt;标题部分。

然后在顶部的项目导航器中自动创建标题的副本。

我从构建阶段删除了它 - &gt;标题并删除了新文件并且工作正常。

喜欢重置或其他什么。

答案 13 :(得分:1)

切换构建设置&gt;允许框架模块中的非模块化包含 YES!为我解决了同样的问题。

答案 14 :(得分:1)

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

答案 15 :(得分:0)

我解决了从框架中删除Modules文件夹的问题。

  • 使用查找器浏览到App Project中存在的框架位置

  • 进入Test.framework文件夹(在上述情况下为SOGraphDB.framework)并删除Modules文件夹。

  • 清理并重新构建应用程序,它将解决该问题。

答案 16 :(得分:0)

在我的情况下(Xcode 9 beta 6 - Swift 4 - 使用Cocoapods),当我删除 Podfile.lock Pods 目录并运行{{1再次

答案 17 :(得分:0)

允许导入非模块化包含后,您可以尝试使用Objective-C Bridging标头导入该模块:

#import <YandexMobileMetrica/YandexMobileMetrica.h>

答案 18 :(得分:0)

最常见的错误是由选择的答案引起的,但是当我将框架文件拖到我的新项目文件夹中时,我偶然会出现这个错误。我点击删除框架,但不小心只按了“删除引用”框架,而不是完全删除文件。此时如果我在Finder中打开我的项目文件夹,我会看到像'CoreLocation'和'AudioToolbox'这样的文件。从项目文件夹中删除这些文件并清理项目修复了问题。

答案 19 :(得分:-1)

我在导入Parse框架时遇到了这个问题。我可以修复它的唯一方法是丢弃自上次提交以来的所有更改(只是删除框架并清理项目不起作用)并再次添加Parse(在重新下载SDK之后)以及其他所需的框架。 / p>