如何从 Swift 调用 Objective-C 代码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24002369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:15:32  来源:igfitidea点击:

How do I call Objective-C code from Swift?

objective-cswift

提问by David Mulder

In Swift, how does one call Objective-C code?

在 Swift 中,如何调用 Objective-C 代码?

Apple mentioned that they could co-exist in one application, but does this mean that one could technically re-use old classes made in Objective-C whilst building new classes in Swift?

Apple 提到它们可以共存于一个应用程序中,但这是否意味着在技术上可以重用在 Objective-C 中创建的旧类,同时在 Swift 中构建新类?

回答by Logan

Using Objective-C Classes in Swift

在 Swift 中使用 Objective-C 类

If you have an existing class that you'd like to use, perform Step 2and then skip to Step 5. (For some cases, I had to add an explicit #import <Foundation/Foundation.hto an older Objective-C File.)

如果您有想要使用的现有类,请执行第 2 步,然后跳到第 5 步。(在某些情况下,我必须在#import <Foundation/Foundation.h旧的 Objective-C 文件中添加一个显式。)

Step 1: Add Objective-C Implementation -- .m

第 1 步:添加 Objective-C 实现——.m

Add a .mfile to your class, and name it CustomObject.m.

.m文件添加到您的类中,并将其命名为CustomObject.m.

Step 2: Add Bridging Header

第 2 步:添加桥接头

When adding your .mfile, you'll likely be hit with a prompt that looks like this:

添加.m文件时,您可能会看到如下提示:

A macOS sheet-style dialog from Xcode asking if you would "like to configure an Objective-C bridging header"

来自 Xcode 的 macOS 工作表样式对话框,询问您是否“想要配置一个 Objective-C 桥接头”

Click Yes!

单击

If you did not see the prompt, or accidentally deleted your bridging header, add a new .hfile to your project and name it <#YourProjectName#>-Bridging-Header.h.

如果您没有看到提示,或者不小心删除了您的桥接头,请.h在您的项目中添加一个新文件并将其命名为<#YourProjectName#>-Bridging-Header.h.

In some situations, particularly when working with Objective-C frameworks, you don't add an Objective-C class explicitly and Xcode can't find the linker. In this case, create your .hfile named as mentioned above, then make sure you link its path in your target's project settings like so:

在某些情况下,尤其是在使用 Objective-C 框架时,您不会显式添加 Objective-C 类,并且 Xcode 找不到链接器。在这种情况下,创建.h如上所述命名的文件,然后确保将其路径链接到目标的项目设置中,如下所示:

An animation demonstrating the above paragraph

演示上述段落的动画

Note:

笔记:

It's best practice to link your project using the $(SRCROOT)macro so that if you move your project, or work on it with others using a remote repository, it will still work. $(SRCROOT)can be thought of as the directory that contains your .xcodeproj file. It might look like this:

最好的做法是使用$(SRCROOT)宏链接您的项目,这样如果您移动您的项目,或与其他人使用远程存储库处理它,它仍然可以工作。$(SRCROOT)可以认为是包含 .xcodeproj 文件的目录。它可能看起来像这样:

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h

Step 3: Add Objective-C Header -- .h

第 3 步:添加 Objective-C 头文件 -- .h

Add another .hfile and name it CustomObject.h.

添加另一个.h文件并将其命名为CustomObject.h.

Step 4: Build your Objective-C Class

第 4 步:构建您的 Objective-C 类

In CustomObject.h

CustomObject.h

#import <Foundation/Foundation.h>

@interface CustomObject : NSObject

@property (strong, nonatomic) id someProperty;

- (void) someMethod;

@end

In CustomObject.m

CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

- (void) someMethod {
    NSLog(@"SomeMethod Ran");
}

@end

Step 5: Add Class to Bridging-Header

第 5 步:将类添加到桥接头

In YourProject-Bridging-Header.h:

YourProject-Bridging-Header.h

#import "CustomObject.h"

Step 6: Use your Object

第 6 步:使用您的对象

In SomeSwiftFile.swift:

SomeSwiftFile.swift

var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

There is no need to import explicitly; that's what the bridging header is for.

无需显式导入;这就是桥接头的用途。

Using Swift Classes in Objective-C

在 Objective-C 中使用 Swift 类

Step 1: Create New Swift Class

第 1 步:创建新的 Swift 类

Add a .swiftfile to your project, and name it MySwiftObject.swift.

将一个.swift文件添加到您的项目中,并将其命名为MySwiftObject.swift.

In 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)"
    }
}

Step 2: Import Swift Files to ObjC Class

第 2 步:将 Swift 文件导入 ObjC 类

In SomeRandomClass.m:

SomeRandomClass.m

#import "<#YourProjectName#>-Swift.h"

The file:<#YourProjectName#>-Swift.hshould already be created automatically in your project, even if you can not see it.

file:<#YourProjectName#>-Swift.h应该已经在您的项目中自动创建,即使您看不到它。

Step 3: Use your class

第 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);

Notes:

笔记:

  1. If Code Completion isn't behaving as you expect, try running a quick build with ??Rto help Xcode find some of the Objective-C code from a Swift context and vice versa.

  2. If you add a .swiftfile to an older project and get the error dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib, try completely restarting Xcode.

  3. While it was originally possible to use pure Swift classes (Not descendents of NSObject) which are visible to Objective-C by using the @objcprefix, this is no longer possible. Now, to be visible in Objective-C, the Swift object must either be a class conforming to NSObjectProtocol(easiest way to do this is to inherit from NSObject), or to be an enummarked @objcwith a raw value of some integer type like Int. You may view the edit history for an example of Swift 1.x code using @objcwithout these restrictions.

  1. 如果 Code Completion 的行为不符合您的预期,请尝试运行快速构建??R以帮助 Xcode 从 Swift 上下文中找到一些 Objective-C 代码,反之亦然。

  2. 如果.swift向旧项目添加文件并出现错误dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib,请尝试完全重新启动 Xcode

  3. 虽然最初可以NSObject通过使用@objc前缀来使用对 Objective-C 可见的纯 Swift 类(不是 的后代),但这不再可能。现在,可见在Objective-C,迅对象必须是符合一类NSObjectProtocol(最简单的方法来做到这一点是要继承NSObject),或者是一个enum标记@objc与一些整数类型等的原始值Int您可以在@objc没有这些限制的情况下查看 Swift 1.x 代码示例的编辑历史记录。

回答by rickster

See Apple's guide to Using Swift with Cocoa and Objective-C. This guide covers how to use Objective-C and C code from Swift and vice versa and has recommendations for how to convert a project or mix and match Objective-C/C and Swift parts in an existing project.

请参阅 Apple 的将 Swift 与 Cocoa 和 Objective-C 结合使用的指南。本指南涵盖了如何使用 Swift 中的 Objective-C 和 C 代码,反之亦然,并提供了有关如何转换项目或在现有项目中混合和匹配 Objective-C/C 和 Swift 部分的建议。

The compiler automatically generates Swift syntax for calling C functions and Objective-C methods. As seen in the documentation, this Objective-C:

编译器会自动生成用于调用 C 函数和 Objective-C 方法的 Swift 语法。正如文档中所见,这个Objective-C:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];

turns into this Swift code:

变成了这个 Swift 代码:

let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)

Xcode also does this translation on the fly — you can use Open Quickly while editing a Swift file and type an Objective-C class name, and it'll take you to a Swift-ified version of the class header. (You can also get this by cmd-clicking on an API symbol in a Swift file.) And all the API reference documentation in the iOS 8and OS X v10.10 (Yosemite)developer libraries is visible in both Objective-C and Swift forms (e.g. UIView).

Xcode 也可以即时进行这种转换——您可以在编辑 Swift 文件时使用 Open Quickly 并输入一个 Objective-C 类名,它会带您到类头的 Swift 化版本。(您也可以通过 cmd-单击 Swift 文件中的 API 符号来获取此信息。)iOS 8OS X v10.10 (Yosemite)开发人员库中的所有 API 参考文档在Objective-C 和 Swift 中都可见形式(例如UIView)。

回答by derrrick

Here are step-by-step instructions for using Objective-C code (in this case, a framework provided by a third-party) in a Swift project:

以下是在 Swift 项目中使用 Objective-C 代码(在本例中为第三方提供的框架)的分步说明:

  1. Add any Objective-C file to your Swift projectby choosing File -> New -> New File -> Objective-C File. Upon saving, Xcode will ask if you want to add a bridging header. Choose 'Yes'. Gif: adding empty file to project and generating bridging header
    (source: derrrick.com)
  1. 通过选择 File -> New -> New File -> Objective-C File,将任何 Objective-C 文件添加到你的 Swift 项目中。保存后,Xcode 会询问您是否要添加桥接头。选择“”。(来源:derrrick.comGif:将空文件添加到项目并生成桥接头

In simple steps:

在简单的步骤:

  1. A prompt appears, and then click on OK... If it does not appear, then we create it manually like in the following... Create one header file from iOS source and give the name ProjectName-Bridging-Header (example: Test-Bridging-Header), and then go to build setting in the Swift compiler code -> Objective-C bridge add Objective-C bridge name ..(Test/Test-Bridging-Header.h). Yeah, that's complete.

  2. Optionally, delete the Objective-C file you added (named "anything" in the GIF image above). You don't need it any more.

  3. Open the bridging header file-- the filename is of the form [YourProject]-Bridging-Header.h. It includes an Xcode-provided comment. Add a line of code for the Objective-C file you want to include, such as a third-party framework. For example, to add Mixpanel to your project, you will need to add the following line of code to the bridging header file:

    #import "Mixpanel.h"
  4. Now in any Swift file you can use existing Objective-C code, in the Swift syntax(in the case of this example, and you can call Mixpanel SDK methods, etc.). You need to familiarize yourself with how Xcode translates Objective-C to Swift. Apple's guideis a quick read. Or see this answer for an incomplete summary.

  1. 出现一个提示,然后点击确定...如果没有出现,那么我们手动创建它,如下所示...从iOS源创建一个头文件并命名为ProjectName-Bridging-Header(例如:Test -Bridging-Header),然后在 Swift 编译器代码中构建设置 -> Objective-C 桥添加 Objective-C 桥名称 ..(Test/Test-Bridging-Header.h)。是的,这就完成了。

  2. 或者,删除您添加的 Objective-C 文件(在上面的 GIF 图像中命名为“anything”)。你不再需要它了。

  3. 打开桥接头文件——文件名的格式为[YourProject]-Bridging-Header.h。它包括 Xcode 提供的注释。为要包含的Objective-C 文件添加一行代码,例如第三方框架。例如,要将 Mixpanel 添加到您的项目,您需要将以下代码行添加到桥接头文件中:

    #import "Mixpanel.h"
  4. 现在,您可以在任何 Swift 文件中使用现有的 Objective-C 代码,采用 Swift 语法(在本示例中,您可以调用 Mixpanel SDK 方法等)。您需要熟悉 Xcode 如何将 Objective-C 转换为 Swift。Apple 的指南是一个快速阅读。或查看此答案以获取不完整的摘要。

Example for Mixpanel:

混合面板示例:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    Mixpanel.sharedInstanceWithToken("your-token")
    return true
}

That's it!

就是这样!

Note: If you remove the bridging header file from your project, be sure to go into Build Settings and remove the value for "Objective-C Bridging Header" under "Swift Compiler - Code Generation".

注意:如果您从项目中删除桥接头文件,请务必进入构建设置并删除“Swift Compiler - Code Generation”下“ Objective-C Bridging Header”的值。

回答by Jake Lin

You can read the nice post Swift & Cocoapods. Basically, we need to create a bridging header file and put all Objective-C headers there. And then we need to reference it from our build settings. After that, we can use the Objective-C code.

您可以阅读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)
  })

Also have a look at Apple's document Using Swift with Cocoa and Objective-Cas well.

也可以看看 Apple 的文档Using Swift with Cocoa and Objective-C

回答by Gian Luigi Romita

I wrote a simple Xcode 6 project that shows how to mix C++, Objective-C and Swift code:

我写了一个简单的 Xcode 6 项目,展示了如何混合 C++、Objective-C 和 Swift 代码:

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

https://github.com/romitagl/shared/tree/master/C-ObjC-Swift/Performance_Console

In particular, the example calls an Objective-C and a C++ function from the Swift.

特别是,该示例从 Swift 调用了一个 Objective-C 和一个 C++ 函数

The key is to create a shared header, Project-Bridging-Header.h, and put the Objective-C headers there.

关键是创建一个共享头文件 Project-Bridging-Header.h,并将 Objective-C 头文件放在那里。

Please download the project as a complete example.

请下载该项目作为完整示例。

回答by Kampai

One more thing I would like to add here:

我还想在这里补充一件事:

I am very thankful for @Logan's answer. It helps a lot to create a bridge file and setups.

我非常感谢@Logan 的回答。创建桥接文件和设置有很大帮助。

But after doing all these steps I'm still not getting an Objective-C class in Swift.

但是在完成所有这些步骤之后,我仍然没有在 Swift 中获得一个 Objective-C 类。

I used the cocoapodslibrary and integrated it into my project. Which is pod "pop".

我使用了该cocoapods库并将其集成到我的项目中。这是pod "pop".

So if you are using Objective-C pods in Swift then there may be a chance that you can not able to get or importthe classes into Swift.

因此,如果您在 Swift 中使用 Objective-C pod,那么您可能无法import将类或类导入 Swift。

The simple thing you have to do is:

您必须做的简单事情是:

  1. Go to <YOUR-PROJECT>-Bridging-Headerfile and
  2. Replace the statement #import <ObjC_Framework>to @import ObjC_Framework
  1. 转到<YOUR-PROJECT>-Bridging-Header文件和
  2. 将语句替换#import <ObjC_Framework>@import ObjC_Framework

For example: (Pop library)

例如:(流行库)

Replace

代替

#import <pop/POP.h>

with

@import pop;

Use clang importwhen #importis not working.

不工作clang import时使用#import

回答by Gergo Erdosi

Quote from the documentation:

文档中引用:

Any Objective-C framework (or C library) that's accessible as a module can be imported directly into Swift. This includes all of the Objective-C system frameworks—such as Foundation, UIKit, and SpriteKit—as well as common C libraries supplied with the system. For example, to import Foundation, simply add this import statement to the top of the Swift file you're working in:

import Foundation

This import makes all of the Foundation APIs—including NSDate, NSURL, NSMutableData, and all of their methods, properties, and categories—directly available in Swift.

任何可作为模块访问的 Objective-C 框架(或 C 库)都可以直接导入 Swift。这包括所有的 Objective-C 系统框架——例如 Foundation、UIKit 和 SpriteKit——以及系统提供的通用 C 库。例如,要导入 Foundation,只需将此导入语句添加到您正在使用的 Swift 文件的顶部:

import Foundation

此导入使所有 Foundation API(包括 NSDate、NSURL、NSMutableData 及其所有方法、属性和类别)在 Swift 中直接可用。

回答by david72

Just a note for whoever is trying to add an Objective-C library to Swift: You should add -ObjCin Build Settings-> Linking-> Other Linker Flags.

对于试图将 Objective-C 库添加到 Swift 的任何人,请注意:您应该在Build Settings-> Linking-> Other Linker Flags 中添加-ObjC

回答by Avijit Nagare

After you created a Bridging header, go to Build Setting => Search for "Objective-C Bridging Header".

创建桥接标头后,转到构建设置 => 搜索“Objective-C 桥接标头”。

Just below you will find the ""Objective-C Generated Interface Header Name" file.

您将在下方找到“Objective-C Generated Interface Header Name”文件。

Import that file in your view controller.

在您的视图控制器中导入该文件。

Example: In my case: "Dauble-Swift.h"

示例:就我而言:“Dauble-Swift.h”

eEter image description here

eEter image description here

回答by Yogesh shelke

Click on the Newfile menu, and chose file select language Objective. At that time it automatically generates a "Objective-C Bridging Header" file that is used to define some class name.

单击新建文件菜单,然后选择文件选择语言目标。那时它会自动生成一个“Objective-C Bridging Header”文件,用于定义一些类名。

"Objective-C Bridging Header" under "Swift Compiler - Code Generation".

“Swift Compiler - Code Generation”下的“Objective-C Bridging Header”。