提问人:David Mulder 提问时间:6/3/2014 最后编辑:TylerHDavid Mulder 更新时间:8/15/2023 访问量:370181
如何从 Swift 调用 Objective-C 代码?
How do I call Objective-C code from Swift?
问:
在 Swift 中,如何调用 Objective-C 代码?
苹果提到它们可以在一个应用程序中共存,但这是否意味着人们可以在技术上重用用 Objective-C 中的旧类,同时在 Swift 中构建新类?
答:
请参阅 Apple 的 Swift 与 Cocoa 和 Objective-C 配合使用指南。本指南介绍了如何使用 Swift 中的 Objective-C 和 C 代码,反之亦然,并就如何在现有项目中转换项目或混合和匹配 Objective-C/C 和 Swift 部分提供了建议。
编译器自动生成用于调用 C 函数和 Objective-C 方法的 Swift 语法。从文档中可以看出,这个 Objective-C:
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
变成这个 Swift 代码:
let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
Xcode 还可以即时进行这种转换——你可以在编辑 Swift 文件时使用 Open Quickly 并键入 Objective-C 类名,它会将你带到类头的 Swift 化版本。(您也可以通过 cmd 单击 Swift 文件中的 API 符号来获取此信息。iOS 8 和 OS X v10.10 (Yosemite) 开发人员库中的所有 API 参考文档都以 Objective-C 和 Swift 形式(例如 UIView
)可见。
评论
引用文档:
任何可作为模块访问的 Objective-C 框架(或 C 库) 可以直接导入 Swift。这包括所有 Objective-C 系统框架,例如 Foundation、UIKit 和 SpriteKit - 以及系统提供的通用 C 库。为 例如,要导入 Foundation,只需将此 import 语句添加到 您正在处理的 Swift 文件的顶部:
import Foundation
此导入使所有 Foundation API(包括 NSDate、NSURL、 NSMutableData 及其所有方法、属性和 类别 - 直接在 Swift 中可用。
在 Swift 中使用 Objective-C 类
如果您有要使用的现有类,请执行步骤 2,然后跳到步骤 5。(在某些情况下,我不得不在较旧的 Objective-C 文件中添加显式。
#import <Foundation/Foundation.h
Step 1: Add Objective-C Implementation -- .分钟
将文件添加到您的类中,并将其命名为 ..m
CustomObject.m
第 2 步:添加桥接标头
添加文件时,您可能会遇到如下所示的提示:.m
单击“是!
如果您没有看到提示,或者不小心删除了桥接标头,请将新文件添加到您的项目中并将其命名为 。.h
<#YourProjectName#>-Bridging-Header.h
在某些情况下,尤其是在使用 Objective-C 框架时,您不会显式添加 Objective-C 类,并且 Xcode 找不到链接器。在这种情况下,请创建如上所述命名的文件,然后确保在目标的项目设置中链接其路径,如下所示:.h
注意:
最佳做法是使用宏链接项目,这样,如果您移动项目,或者使用远程存储库与其他人一起处理项目,它仍然可以工作。 可以将其视为包含 .xcodeProj 文件的目录。它可能看起来像这样:$(SRCROOT)
$(SRCROOT)
$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h
第 3 步:添加 Objective-C 头文件 -- .h
添加另一个文件并将其命名为 。.h
CustomObject.h
第 4 步:构建 Objective-C 类
在CustomObject.h
#import <Foundation/Foundation.h>
@interface CustomObject : NSObject
@property (strong, nonatomic) id someProperty;
- (void) someMethod;
@end
在CustomObject.m
#import "CustomObject.h"
@implementation CustomObject
- (void) someMethod {
NSLog(@"SomeMethod Ran");
}
@end
第 5 步:向 Bridging-header 添加类
在:YourProject-Bridging-Header.h
#import "CustomObject.h"
第 6 步:使用对象
在:SomeSwiftFile.swift
var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()
无需显式导入;这就是桥接头的用途。
在 Objective-C 中使用 Swift 类
第 1 步:创建新的 Swift 类
将文件添加到项目中,并将其命名为 。.swift
MySwiftObject.swift
在:MySwiftObject.swift
import Foundation
@objc(MySwiftObject)
class MySwiftObject : NSObject {
@objc
var someProperty: AnyObject = "Some Initializer Val" as NSString
init() {}
@objc
func someFunction(someArg: Any) -> NSString {
return "You sent me \(someArg)"
}
}
第 2 步:将 Swift 文件导入 ObjC 类
在:SomeRandomClass.m
#import "<#YourProjectName#>-Swift.h"
该文件:应该已经在您的项目中自动创建,即使您看不到它。<#YourProjectName#>-Swift.h
第 3 步:使用课程
MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];
NSLog(@"RetString: %@", retString);
笔记:
如果代码完成功能未按预期运行,请尝试运行快速构建,以帮助 Xcode 从 Swift 上下文中找到一些 Objective-C 代码,反之亦然。⌘⇧R
如果您将文件添加到较旧的项目并收到错误,请尝试完全重新启动 Xcode。
.swift
dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib
虽然最初可以使用纯 Swift 类(不是 的后代),这些类通过使用前缀对 Objective-C 可见,但这不再可能。现在,要在 Objective-C 中可见,Swift 对象必须是符合的类(最简单的方法是继承自 ),或者是用某种整数类型的原始值标记的,例如 。您可以查看使用
@objc
的 Swift 1.x 代码示例的编辑历史记录,而不受这些限制。NSObject
@objc
NSObjectProtocol
NSObject
enum
@objc
Int
评论
你可以阅读 Swift & Cocoapods 的好文章。基本上,我们需要创建一个桥接头文件,并将所有 Objective-C 头文件放在那里。然后我们需要从我们的构建设置中引用它。之后,我们可以使用 Objective-C 代码。
let manager = AFHTTPRequestOperationManager()
manager.GET(
"http://example.com/resources.json",
parameters: nil,
success: { (operation: AFHTTPRequestOperation!,
responseObject: AnyObject!) in
println("JSON: " + responseObject.description)
},
failure: { (operation: AFHTTPRequestOperation!,
error: NSError!) in
println("Error: " + error.localizedDescription)
})
也可以看看 Apple 的文档 Using Swift with Cocoa and Objective-C。
我写了一个简单的Xcode 6项目,展示了如何混合C++,Objective-C和Swift代码:
https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console
特别是,该示例从 Swift 调用 Objective-C 和 C++ 函数。
关键是创建一个共享标头 Project-Bridging-Header.h,并将 Objective-C 标头放在其中。
请下载该项目作为完整示例。
以下是在 Swift 项目中使用 Objective-C 代码(在本例中为第三方提供的框架)的分步说明:
- 通过选择“文件”-“新建”-“新建文件”->“Objective-C 文件”,将任何 Objective-C 文件添加到 Swift 项目中>>新建文件。保存后,Xcode 会询问您是否要添加桥接标头。选择“是”。
(来源:derrrick.com)
只需简单的步骤:
出现提示,然后单击“确定...”如果它没有出现,那么我们手动创建它,如下所示......从 iOS 源代码创建一个头文件,并命名为 ProjectName-Bridging-Header(例如:Test-Bridging-Header),然后转到 Swift 编译器代码中的构建设置> Objective-C 桥接添加 Objective-C 桥接名称。(测试/Test-Bridging-Header.h)。是的,这就完成了。
或者,删除您添加的 Objective-C 文件(在上面的 GIF 图像中名为“anything”)。你不再需要它了。
打开桥接头文件 -- 文件名的格式为 [YourProject]-Bridging-Header.h。它包括 Xcode 提供的注释。为要包含的 Objective-C 文件(如第三方框架)添加一行代码。例如,若要将 Mixpanel 添加到项目中,需要将以下代码行添加到桥接头文件中:
#import "Mixpanel.h"
现在,在任何 Swift 文件中,您都可以使用 Swift 语法(在本例中,您可以调用 Mixpanel SDK 方法等)使用现有的 Objective-C 代码。您需要熟悉 Xcode 如何将 Objective-C 转换为 Swift。Apple 的指南是快速阅读的。或者查看此答案以获取不完整的摘要。
Mixpanel 示例:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
Mixpanel.sharedInstanceWithToken("your-token")
return true
}
就是这样!
注意:如果从项目中删除桥接头文件,请务必进入 Build Settings 并删除 “Swift Compiler - Code Generation” 下的 “Objective-C Bridging Header” 值。
单击“新建文件”菜单,然后选择“文件选择语言目标”。此时,它会自动生成一个“Objective-C Bridging Header”文件,用于定义某个类名。
“Swift Compiler - Code Generation”下的“Objective-C Bridging Header”。
我还想在这里补充一点:
我非常感谢@Logan的回答。它对创建桥接文件和设置有很大帮助。
但是在完成所有这些步骤之后,我仍然没有在 Swift 中获得 Objective-C 类。
我使用了该库并将其集成到我的项目中。这是.cocoapods
pod "pop"
因此,如果你在 Swift 中使用 Objective-C pod,那么你可能无法将类导入 Swift。import
你要做的简单的事情是:
- 转到文件并
<YOUR-PROJECT>-Bridging-Header
- 将语句替换为
#import <ObjC_Framework>
@import ObjC_Framework
例如:(Pop library)
取代
#import <pop/POP.h>
跟
@import pop;
当 #import
不工作时,请使用 clang import
。
评论
创建桥接头文件后,转到 Build Setting => 搜索 “Objective-C Bridging Header”。
在正下方,您将找到“Objective-C 生成的接口头名称”文件。
在视图控制器中导入该文件。
示例:在我的例子中:“Dauble-Swift.h”
对于试图向 Swift 添加 Objective-C 库的人,请注意:您应该在 Build Settings -> Linking -> Other Linker Flags 中添加 -ObjC。
评论
- 从 NewFile -> Source -> 头文件创建 .h 文件
- 然后保存文件的名称 Your_Target_Name-Bridging-Header.h 这里的人通过获取他们的项目名称而犯了常见的错误,但如果两者不同,它应该是项目的目标名称,通常它们是相同的。
- 然后在构建设置中搜索 Objective-C 桥接标头标志并输入新创建的桥接文件的地址,您可以右键单击文件 - >显示在查找器中 - >将文件拖动到文本区域,然后地址将被填充。
- 使用 #import Your_Objective-C_file.h
- 在 swift 文件中,您可以访问 ObjC 文件,但只能使用 swift 语言。
在 Swift 中使用 objective-c 编码的两种方法
1
1. Create bridge-header.h file in Xcode Project
2. import .h file in bridge-Header file
3. Set path of bridge-Header in Build settings.
3. Clean the Project
2
1. Create objective-c files in project(it automatically set path in Build Settings for you )
2. import .h file in bridge-Header file
在 Xcode 10.1 的 Swift 4.2.1 项目中,您可以轻松添加 Objective-C 文件。按照以下步骤将 Objective-C 文件桥接到 Swift 项目。
Step_01:使用 Swift 语言创建新的 Xcode 项目:
File
> New
> Project
> objc
.
Step_02:在 Swift 项目中添加新的 Objective-C 文件:
File
> New
> File...
> macOS
> Objective-C File
.
Step_03:如果你在第一次向 Swift 项目中添加一个新的 Objective-C 文件,Xcode 会询问你:
Would you like to configure an Objective-C bridging header
?
Step_04:选择以下选项:
Create Bridging Header
.
Step_05:将生成一个名称为:
Objc-Bridging-Header.h
.
Step_06:现在,您需要在桥接头中设置桥接文件路径。在“项目导航器”中,单击“带名称的项目”,然后选择:objc
Build Settings
> Objective-C Bridging Header
> Objc-Bridging-Header.h
.
Step_07:将 your 拖放到该框中以生成文件路径。Objc-Bridging-Header.h
Step_08:打开文件并导入要在 Swift 文件中使用的 Objective-C 文件。Objc-Bridging-Header.h
#import "SpecialObjcFile.m"
以下是以下内容:SpecialObjcFile.m
#import <Foundation/Foundation.h>
@interface Person: NSObject {
@public
bool busy;
}
@property
bool busy;
@end
Step_09:现在在你的 Swift 文件中,你可以使用 Objective-C 类:
override func viewDidLoad() {
super.viewDidLoad()
let myObjcContent = Person()
print(myObjcContent.busy)
}
Apple 在此文档中提供了官方指南:how-to-call-objective-c-code-from-swift
以下是相关部分:
若要将一组 Objective-C 文件导入到同一应用目标中的 Swift 代码中,需要依靠 Objective-C 桥接头文件将这些文件公开给 Swift。当您将 Swift 文件添加到现有 Objective-C 应用或将 Objective-C 文件添加到现有 Swift 应用时,Xcode 会创建此标头。
如果您接受,Xcode 将创建桥接头文件以及您正在创建的文件,并使用您的产品模块名称后跟“-Bridging-Header.h”对其进行命名。或者,您也可以通过选择“文件”>“新建>文件”>“[操作系统]”>“源>头文件”来自行创建桥接头
编辑桥接标头,将 Objective-C 代码公开给 Swift 代码:
- 在 Objective-C 桥接头文件中,导入要公开给 Swift 的每个 Objective-C 头文件。
- 在“生成设置”的“Swift 编译器 - 代码生成”中,确保“Objective-C 桥接头文件”生成设置具有桥接头文件的路径。该路径应相对于项目,类似于在“生成设置”中指定 Info.plist 路径的方式。在大多数情况下,您不需要修改此设置。
桥接标头中列出的任何公共 Objective-C 标头对 Swift 都是可见的。
Logans 的答案工作正常,除了在最新时它给出了一些编译器错误。这是针对正在使用 Swift 5 的人的修复程序。Swift 5
斯威夫特 5
import Foundation
class MySwiftObject : NSObject {
var someProperty: AnyObject = "Some Initializer Val" as AnyObject
override init() {}
func someFunction(someArg:AnyObject) -> String {
let returnVal = "You sent me \(someArg)"
return returnVal
}
}
混合使用 Objective-C 和 Swift
高电平图:

同一目标
//Objective-C exposes API for Swift through <target_name>-Bridging-Header.h
.swift uses .h.m = Swift consumer, Objective-C producer = <target_name>-Bridging-Header.h
//Swift exposes API for Objective-C through <target_name>-Swift.h
.h.m uses .swift = Objective-C consumer, Swift producer = <target_name>-Swift.h
Swift 消费者,Objective-C 生产者
添加新的头文件和实现文件 - Cocoa 类文件(Objective-C)
例如和.h
.m
<MyFileName>.h
<MyFileName>.m
配置桥接标头
当您看到单击 - 是Would you like to configure an Objective-C bridging header
<target_name>-Bridging-Header.h
将自动生成- 构建设置 -> Objective-C 桥接头文件(SWIFT_OBJC_BRIDGING_HEADER)
将类添加到桥接头
在添加一行<target_name>-Bridging-Header.h
#import "<MyFileName>.h"
之后,您可以使用 from ,Swift
Objective-C's
MyFileName.h
MyFileName.m
P.S. 如果你应该将现有的 Objective-C 文件添加到 Swift 项目中,请事先添加并导入它Bridging-Header.h
Objective-C 消费者,Swift 生产者
添加 a 和 extends
<MyFileName>.swift
NSObject
将 Swift 文件导入 ObjC 类
添加到您的 Objective-C 文件中#import "<target_name>-Swift.h"
通过 [关于] 公开公共 Swift 代码
@objc
之后,您可以使用Objective-C
Swift's
<MyFileName>.swift
[未找到 <product_name>-Swift.h 文件]
不同的目标 [.modulemap] 和 [umbrella.h] 用于公开 Swift 的 Objective-C。以及用于公开 Objective-C 的 Swift 代码Swift.h
使任何 Swift 类成为 NSObject 的子类也是有意义的,我更喜欢使用任何 Swift 类在 Objective-C 类中看到,例如:
@objc(MySwiftClass)
@objcMembers class MySwiftClass {...}
评论