如何在Swift框架中导入私有框架头文件?

时间:2015-02-26 15:21:13

标签: ios objective-c swift clang

我有一个Objective-C框架(框架A),它公开了一些公共标题和一些私有标题。公共标题也在框架的标题中声明。我有第二个与Objective-C框架链接的Swift框架(框架B)。

现在,如果我想在B中导入A的公共标题,我只需要import A

但是如何导入私有标题?

我知道桥接标题不是一个选项,因为框架不支持它。我是否需要以某种方式为私有标题创建单独的伞标题?

4 个答案:

答案 0 :(得分:25)

您需要修改框架A,以便导出私有模块。

  1. A项目中创建private module map file。这将是这样的:

    <强> A / private.modulemap

    explicit module A.Private {
    
        // Here is the list of your private headers.
        header "Private1.h"
        header "Private2.h"
    
        export *
    }
    
  2. 在框架A目标的“构建设置”中,搜索“私有模块地图文件”行,并进行以下操作:

    $(SRCROOT)/A/private.modulemap
    
  3. 不要在“编译源代码”中包含private.modulemap文件。这会导致不必要的警告。

  4. 清理和构建框架A目标。

  5. 在框架B Swift文件中。您可以像这样导入私有模块:

    import A
    import A.Private
    

答案 1 :(得分:2)

此问题发布已经有一段时间了。可接受的答案非常好,就我而言,这是一种常见的方法。

问题是,它不是真正的“私有” 。您可以在框架内执行此操作以访问“私人”部分:

// Framework A Swift file
import A.Private

但是,如果您在应用程序中使用框架A(或将其交付给客户),他仍然可以:

// Client App Swift file
import A
import A.Private

// access "private" framework methods and classes

我正在尝试解决这一问题,因为最近我遇到了一种情况,需要将其隐藏在用户面前(封闭源框架)-我只是不允许任何人访问它,因为这对SDK完整性构成威胁。

我找到了解决该问题的方法,但是太复杂了,无法将其整体粘贴到这里。

我对此发表了评论。也许它将帮助某人检查该问题,这是我的文章的链接:

https://medium.com/@amichnia_31596/creating-swift-framework-with-private-objective-c-members-the-good-the-bad-and-the-ugly-4d726386644b

答案 2 :(得分:2)

正如Andrzej Michnia在回答中所注意到的那样,“私有模块映射”解决方案的问题在于它并不是完全私有的,并且那些“私有”标头仍然可以被某些人看到,因为它们仍然包含在我们的框架中。如果有人使用这种“私有”模块打开编译的框架,他仍然会看到您隐藏的所有.h文件。

如果我们需要向其他用户完全隐藏swift框架中的一些Objective-C标头,那么另一种可行的方法是将它们公开,并在手动或使用bash构建框架后将其从我们的框架中删除脚本。

您可以创建一个单独的头文件,例如“ InternalHeaders.h”,在其中导入您不想公开的所有头文件。然后,将此InternalHeaders.h导入框架的公共伞式标题中。公开所有标头,以便您可以编译所有内容。构建框架后,只需从公共伞形标题中删除“ import InternalHeaders.h”,然后删除所有您不想手动或使用bash脚本或在运行脚本构建阶段中公开的标题即可。

仍然不是一个完美的解决方案,但是在某些情况下,迅速编写协议以匹配其他答案中提出的每个Objective-C接口可能会更容易,更快捷。

答案 3 :(得分:0)

我的情况可能会因我的设置而异,但是如果有其他帮助,我会在这里提供。我还有一个带有私有标头的Objective-C框架(框架A),我需要在链接它的Swift框架(框架B)中使用它。其他一些细节:

  1. 每个框架都位于工作区中的一个单独项目中

  2. 该项目使用CocoaPods

  3. podspec定义了两个框架之间的以下依赖关系:

    s.subspec 'FrameworkA' do |cs|
        cs.vendored_frameworks = "lib/FrameworkA.framework"
    end
    
    s.subspec 'FrameworkB' do |ts|
        ts.dependency 'FrameworkA'
        ts.vendored_frameworks = "lib/FrameworkB.framework"
    end
    

@rintaro提供的解决方案在Xcode中运行时对我来说非常有效,但是一旦部署了Pod,FrameworkB就无法使用{{1 }}。对我有用的是在私有modulemap中使用相对于FrameworkA目录的相对路径:

PrivateHeaders

这在使用CocoaPods安装的最终产品中的Xcode 中有效。这有点骇人听闻,因为它在最终的构建产品中引用了一个文件夹,如果还有其他方法可以告诉CocoaPods如何保存这些路径,我也不会感到惊讶,但是无论如何,我都没有找到它。现在可以解决问题。