将Objective-C框架连接到Swift iOS 8应用程序(Parse框架)

55

我正在尝试在iOS 8开发中使用Swift编程语言来使用一个Objective-C框架。这是导入的一种特定情况,但是一般问题是:

如何将Objective-C框架导入到Swift中并使导入得到识别?

我正在使用iOS 8和Xcode 6beta尝试将Parse框架集成到一个Swift应用程序中。

以下是在Objective-C中集成Parse框架的技巧:

https://www.parse.com/apps/quickstart#social/mobile/ios/native/existing

我已将Parse框架作为压缩档案下载并解压缩,并将其无误地导入到Xcode 6中。在我的应用程序中,它显示为名称为Parse.framework的正确格式化框架。

我当前的想法是修改项目根目录下的AppDelegate.swift文件。以下是未经修改的当前文件(由Xcode在swift项目创建时自动生成):

https://gist.github.com/fconcklin/e8ef7d8b056105a04161

我尝试通过在import UIKit下添加import Parse来导入Parse。然而,Xcode发出警告说找不到此模块,构建失败。

我还尝试创建一个名为${PROJ_NAME_HERE}-Bridging-Header.h的文件,其中包含使用import <Parse/Parse.h>的Objective-C导入Parse。这条线路没有引发错误,但似乎最终没有任何影响。


1
项目属性中是否设置了桥接头文件的路径?打开项目属性,查找“Swift编译器 - 代码生成”部分下的“Objective-C桥接头文件”。仅有桥接头文件是不够的 - 您必须在项目中设置其路径。 - Brian Walker
6个回答

80

经过进一步的研究,我找到了解决方案并意识到自己只是困惑了。

正确的方法如下:

  • 通过将框架拖放到 Xcode 6 Swift 项目中来导入您的 Objective C 框架。

  • 在您的项目中创建一个新的 Objective C 文件(文件->新建->文件 [Objective C for iOS])。

  • 接受提示(同意)以在 Objective C 和 Swift 之间创建桥接头文件。

  • 删除您新创建的 Objective C 文件,但保留桥接头文件 ${YOURPROJ}-Bridging-Header.h

  • 在桥接头文件中,使用标准的Objective C导入语法(例如#import <Parse/Parse.h>)导入您的框架。

  • 这样就不需要在您的AppDelegate.swift文件中执行import Parse语句了。现在,只要使用桥接头导入了任何框架,就可以编写利用该框架的代码。它在整个项目的 Swift 文件中都可用。

现在,如果您想在项目中测试Parse集成,可以键入Parse.并使用代码完成浏览框架,看到代码完成指示成功导入。

然而,在使用桥接头文件时还有另一个需要解决的注意事项。所有框架的依赖关系也需要在桥接头文件中指定。在将Parse框架集成到Swift应用程序中的情况下,您的桥接头文件将如下所示:

 #import <Foundation/Foundation.h>

 // Parse Dependencies
 #import <AudioToolbox/AudioToolbox.h>
 #import <CFNetwork/CFNetwork.h>
 #import <CoreGraphics/CoreGraphics.h>
 #import <CoreLocation/CoreLocation.h>
 #import <MobileCoreServices/MobileCoreServices.h>
 #import <QuartzCore/QuartzCore.h>
 #import <Security/Security.h>
 #import <StoreKit/StoreKit.h>
 #import <SystemConfiguration/SystemConfiguration.h>

 // Import parse framework
 #import <Parse/Parse.h>

希望这能有所帮助。

谢谢您的回复,它真的很有效。问题在于很难意识到您不必在 Swift 文件中导入 Parse! - Jorge Vicente Mendoza
当我这样做并转到另一个Swift文件时,我会无限期地收到“SourceKitService崩溃。编辑器功能暂时受限”的消息,直到我删除头文件。 - mginn
2
它还能工作吗?我得到了failed to import bridging header '/PATH/TO/File-Bridging-Header.h',然后是error: 'Parse/Parse.h' file not found - Stefano Munarini

50
一种“傻瓜式”的添加桥接头文件的方法如下:
如果您有一个Swift项目,在项目中添加一个新的Objective-C文件,Xcode会提示您是否要使用桥接头来配置您的项目。点击"是"。
如果您有一个Objective-C项目,在其中添加一个新的Swift文件,您将得到相同的提示。点击"是"。
获取桥接头文件后,如果您想要的话,可以删除刚刚添加的文件。

3
我有一个 Swift 项目,但是当我添加 ObjC 头文件(Xcode 6 b4)时,无法让“add bridging header”消息出现。有什么想法吗? - ZuluDeltaNiner
@ZuluDeltaNiner 我之前也遇到了同样的问题,直到我意识到我已经导入了另一个框架,该框架已经创建了桥接类。你是否已经创建了桥接头文件类呢? - Maxwell
我尝试过这种技术,但我得到的只是一个空的桥接头文件。 - William Grand
我已经有桥接头文件了,但由于该框架是 Objective-C 的,而 Xcode 8 不允许在 Swift 项目中使用,因此出现了错误,我该怎么办? - Eduardo Oliveros

10

4

在Swift中使用Objective-C类

如果你要在应用程序目标中导入代码(混合Swift和Objective-C的项目),你应该使用bridging header文件将Objective-C代码暴露给Swift代码。[在项目中混合Swift和Objective-C代码]

本文将介绍如何将Objective-C框架导入到Swift代码中。

Swift客户端-> Objective-C动态框架

Xcode版本10.2.1

创建Objective-C框架

创建一个框架项目或创建一个框架目标

File -> New -> Project... -> Cocoa Touch Framework
//or
Project editor -> Add a Target -> Cocoa Touch Framework

将生成两个文件:

  1. Info.plist - 构建设置 -> Info.plist 文件
  2. <product_name>.h - 构建阶段 -> 标头。这是一个包含所有公开接口的总头文件,供使用者引用[关于]

将所有 .h 文件添加到这个总头文件(<product_name>.h)中

#import "header_1.h"
#import "header_2.h"

添加实现文件 .m
Select `.m` file -> Select File Inspectors Tab -> Target Membership -> Select the target
//or
Project editor -> select a target -> Build Phases -> Compile Sources -> add files

添加在公共区域中 <product_name>.h 中列出的头文件 .hheader_1.hheader_2.h[无法完成] [公共目标成员资格]

Select `.h` file -> Select File Inspectors Tab -> Target Membership -> Select the target and make it **public**
//or
Project editor -> select a target -> Build Phases -> Headers -> add files to the **public** zone

构建框架 - ⌘ Command + B 产品 -> 构建 注意:确保您为与客户端代码相同的进程架构构建框架。
查找生成的输出[生成位置]
Products group -> <product_name>.framework -> Show in Finder

该框架包括:

  • Info.plist
  • Modules文件夹,其中包含:
  • module.modulemap[关于] [自定义modulemap]此文件的生成是因为构建设置 -> 定义模块 -> 是
  • Headers文件夹,其中包含:
  • Headers部分中的文件。这里是公共接口/定义

使用Objective-C框架的Swift消费者

拖放二进制文件到Xcode项目[关于]

嵌入二进制文件[未加载库] [链接 vs 嵌入]

Project editor -> select a target -> General -> Embedded Binaries -> path to `<product_name>.framework` file

我将自动将框架添加到以下位置:
  1. 项目编辑器 -> 选择目标 -> 常规 -> 链接的框架和库
  2. 项目编辑器 -> 选择目标 -> 构建阶段 -> 嵌入式框架
  3. 项目编辑器 -> 选择目标 -> 构建阶段 -> 链接二进制文件
添加Framework Search paths(FRAMEWORK_SEARCH_PATHS)[模块未找到] [递归路径]
Project editor -> select a target -> Build Settings -> Search Paths -> Framework Search paths -> add path to the parent of `<product_name>.framework` file

将模块导入到Swift客户端代码中[模块名称]

import module_name

这里有更多的示例


我们如何在Swift框架中使用module map消耗Objective-C xcframework? 我有这个: “模块ObjCHyperPayModule{ 头部"../Frameworks/OPPWAMobile.xcframework/ios-arm64_armv7/OPPWAMobile.framework/Headers/OPPWAMobile.h" //头部"../Frameworks/OPPWAMobile.xcframework/ios-arm64_i386_x86_64-simulator/OPPWAMobile.framework/Headers/OPPWAMobile.h" //${SRCROOT} 导出* }” - hasan

3
我的问题的答案与众不同。我在项目的构建设置中将框架搜索路径设置为递归,而应该是非递归
在我的情况下,我的目标的框架搜索路径设置为$(inherited),这意味着从我的项目中继承设置。
我的项目的框架搜索路径只有一个路径,$PROJECT_DIR/../External/**(两个星号表示“递归搜索此文件夹”)。我的Parse.framework文件位于External文件夹的基本级别。
将路径从递归更改为非递归对我来说解决了问题。非常奇怪...

1
新的Parse框架版本需要一些更新。
例如,您应该在“库二进制文件”中插入libsqlite3.0.dylib,并使用#import和#import更新头文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接