将 Objective-c 框架导入 Swift 框架(Google Analytics + Cocoapod)

Import Objective-c framework into Swift framework (Google Analytics + Cocoapod)

我正在尝试将我常用的 Swift 代码集中到一个框架中,并且该代码的一部分使用 Google 分析。我将 Google Analytics 作为 Cocoapod 引入,但我无法像从原始项目那样从新框架访问它,因为它是 Objective-C 并且框架中没有桥接 header 支持[我正在使用 Swift 1.2]。

我通常在桥接 header 中使用的代码行是:

#import <Google/Analytics.h>

我到底应该把它放在我的项目中的什么地方才能使这一切像以前在桥接中一样工作?header?

我在Apple's documentation about mixing Swift and Objective-C中找到的是这样的:

Importing Code from Within the Same Framework Target

If you’re writing a mixed-language framework, you may need to access your Objective-C code from Swift and your Swift code from Objective-C.

Importing Objective-C into Swift

To import a set of Objective-C files in the same framework target as your Swift code, you’ll need to import those files into the Objective-C umbrella header for the framework.

To import Objective-C code into Swift from the same framework

Under Build Settings, in Packaging, make sure the Defines Module setting for that framework target is set to Yes. In your umbrella header file, import every Objective-C header you want to expose to Swift. For example: OBJECTIVE-C

import <XYZ/XYZCustomCell.h>

import <XYZ/XYZCustomView.h>

import <XYZ/XYZCustomViewController.h>

我认为最相关的短语是:

you’ll need to import those files into the Objective-C umbrella header for the framework

但是这个文件是什么以及如何创建它?

Apple 的文档前面提到(在table):

Objective-C code

Import into Swift

#import "Header.h"

好吧,我试过只创建一个文件 "Header.h" 并导入它,但这不起作用。我不知道他们想表达什么。我在构建设置中找不到 "umbrella" 任何内容。

所以我的问题是,如何在我的 Swift 项目中导入此文件 (#import ),以便它可以看到 Google Analytics cocoapod框架就像我通常在桥接一个普通项目时所做的那样header?

更新:

我开始相信 objective-c 桥接 header 可能是与项目同名的 .h 文件。我现在尝试在那里添加导入语句,我得到的错误是:

! Include of non-modular header inside framework module 'JBS'

桥接头文件是将 Objective-C 文件用于 Swift 框架的特定头文件。

您可以在 Apple doc 中找到有关 桥接 的更多信息:

Xcode creates the header file along with the file you were creating, and names it by your product module name followed by adding "-Bridging-Header.h". (You’ll learn more about the product module name later, in Naming Your Product Module.)

所以您唯一要做的就是通过选择

手动创建该文件

File > New > File > (iOS, watchOS, tvOS, or OS X) > Source > Header File.

如果你的框架名称是ABC,那么头文件的名称应该是:

ex : ABC-Bridging-Header.h

你可以把它放在你的框架项目中你想要的地方。

希望这可以帮助到别人!

解决方案不像应用程序那么简单。我们必须创建一个模块映射。

看看this example repo

Inside Swift code we can only import so called modules. The trick is to define a module which in turn contains all the ObjC headers that we need the Swift code to access.

this article 的模块映射部分也可能对您有所帮助。

As convenient as the bridging header is, it has one key limitation—you can’t use it inside a framework project. The alternative is to use a module.

To do this, create a directory in your project directory named after the library you want to use. I did this in the shell, outside Xcode’s auspices, naming it CommonCrypto. Inside the directory, create a module.map file that encapsulates library settings. For CommonCrypto, module.map looks like this:

module CommonCrypto [system] { header "/usr/include/CommonCrypto/CommonCrypto.h" export * }

Now add the new module to Import Paths under Swift Compiler – Search Paths in your project settings. Use ${SRCROOT} in the module path (e.g. ${SRCROOT}/CommonCrypto) to insure that the project works no matter where it’s checked out.

This makes it possible to just import CommonCrypto in your Swift files. Note that consumers of any frameworks you build using this technique are also going to have to add the module to their Swift search paths.

我遵循了上面文章中的步骤,并以这种方式满足了我的需要:

module Muse { header "Muse.framework/Headers/Muse.h" export * }

为了安全起见,我删除了 [system] 词库(因为它删除了警告),并将框架放在与 module.map 文件相同的文件夹中。

此外,如果需要,请不要忘记在您的框架目标中包含 libc++.tbd 和其他必需的依赖项(在 General 选项卡的 Linked Frameworks and Libraries 部分)。

对于那些一直问我是否解决了这个问题的人,下面是我如何完成将 KochavaTracker SDK Cocoapod 导入框架的任务。该 SDK 目前是用 Objective-C 编写的。此答案基于 nuKs 提供的答案,具有这些特定步骤。

1) 在您的项目文件夹下创建一个名为 KochavaTracker 的文件夹,即 MyFramework/MyFramework/KochavaTracker.

2) 在该文件夹中创建一个名为 module.modulemap 的文件并插入以下内容:

/*
 This is the private module which is used to make private ObjC headers available to Swift code.
 Note how all header files need to be specified with paths relative to this file.

 This file lives inside a folder, and that folder is the actual module. In Xcode the SWIFT_INCLUDE_PATHS needs to include the parent directory to that folder.
 */
module KochavaTracker {
    header "../../Pods/KochavaTrackeriOS/KochavaTrackeriOS/Classes/KochavaTracker.h"
    export *
}

这有效地创建了一个模块,它是 SDK 接口的包装器,Swift 稍后可以像导入其他 Swift 模块一样导入。请注意,它依赖于 Pods 文件夹的相对路径。

3) 如构建设置中所见,修改您的 SWIFT_INCLUDE_PATHS 以包括:

$(SRCROOT)/KochavaTracker

这样一来,您就可以导入该模块,它会将它定位到 in/as 您在其下创建的 KochavaTracker 文件夹。

4) 在适当的地方添加到您的 Swift 代码中:

import KochavaTracker

从那里您应该能够引用 KochavaTracker 模块中的 类。