如何从Swift调用Objective-C代码

问题描述 投票:902回答:16

In the new Swift language from Apple, how does one call Objective-C code?

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

The Reasoning

Objective-C是一种独立于平台的语言,而Swift则依赖于平台。因此,在Swift中编写非平台相关代码(业务逻辑库)并不明智。但是,在其中编写与平台相关的代码(例如,与接口相关)将非常好。不是说这是一个好主意,但它肯定是一种兴趣。

objective-c swift
16个回答
1322
投票

Using Objective-C Classes in Swift

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

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

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

Step 2: Add Bridging Header

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

单击是!

如果您没有看到提示或意外删除了桥接标题,请将新的.h文件添加到项目中并将其命名为<#YourProjectName#>-Bridging-Header.h

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

注意

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

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

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

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

Step 4: Build your Objective-C Class

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

Step 5: Add Class to Bridging-Header

YourProject-Bridging-Header.h

#import "CustomObject.h"

Step 6: Use your Object

SomeSwiftFile.swift

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

无需明确导入;这就是桥接头的用途。

Using Swift Classes in Objective-C

Step 1: Create New Swift Class

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

MySwiftObject.swift

import Foundation

class MySwiftObject : NSObject {

    var someProperty: AnyObject = "Some Initializer Val"

    init() {}

    func someFunction(someArg:AnyObject) -> String {
        var returnVal = "You sent me \(someArg)"
        return returnVal
    }   
}

Step 2: Import Swift Files to ObjC Class

SomeRandomClass.m

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

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

Step 3: Use your class

MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);

// original
NSString * retString = [myOb someFunction:@"Arg"];
// xcode10 expands the external arg here
NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];|

NSLog(@"RetString: %@", retString);

注意:

1. CodeCompletion的表现并不像我想的那么准确。在我的系统上,使用“cmd + r”运行快速构建似乎有助于Swift找到一些Objective-C代码,反之亦然。

2.如果您将.swift文件添加到较旧的项目并收到错误:dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib,请尝试完全restarting Xcode

3.虽然最初可以通过使用@objc前缀在Objective-C中使用纯Swift类,但在Swift 2.0之后,这已不再可能。有关原始说明,请参阅编辑历史如果在将来的Swift版本中重新启用此功能,则答案将相应更新。


4
投票

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

“Swift编译器 - 代码生成”下的“Objective-C Bridging Header”。


3
投票
  1. 从NewFile - > Source - >头文件创建一个.h文件
  2. 然后保存文件的名称Your_Target_Name-Bridging-Header.h这里的人们通过获取他们的项目名称会遇到常见错误,但如果两者都不同,它们应该是Project的Target名称,通常它们是相同的。
  3. 然后在构建设置中搜索Objective-C Bridging Header标志并输入新创建的桥接文件的地址,你可以右键单击文件 - >在finder中显示 - >在文本区域中拖动文件然后地址将被填充。
  4. 使用#import Your_Objective-C_file.h
  5. 在swift文件中,您可以访问ObjC文件,但只能使用swift语言。

3
投票

enter image description hereI已经在github上添加了包含小样本的项目来调用来自swift的目标c代码。

Call ObjectiveC class from swift


2
投票

在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

enter image description here

Step_04:选择选项:

Create Bridging Header

Step_05:将生成一个名称相应的文件:

Objc-Bridging-Header.h

enter image description here

Step_06:现在,您需要在桥接头中设置Bridge文件路径。在Project Navigator中,单击名为objc的项目,然后选择:

Build Settings> Objective-C Bridging Header> Objc-Bridging-Header.h

Step_07:将你的Objc-Bridging-Header.h拖放到该框中以生成文件路径。

enter image description here

Step_08:打开Objc-Bridging-Header.h文件并导入要在Swift文件中使用的Objective-C文件。

#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)
}

enter image description here enter image description here


0
投票

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代码:

  1. 在Objective-C桥接头中,导入要向Swift公开的每个Objective-C头。
  2. 在Build Settings中,在Swift编译器 - 代码生成中,确保Objective-C Bridging Header构建设置具有桥接头文件的路径。路径应该与项目相关,类似于在“构建设置”中指定Info.plist路径的方式。在大多数情况下,您无需修改​​此设置。

Swift可以看到桥接头中列出的任何公共Objective-C头。


0
投票

双向使用objective-c objective-c的方法

1

  1. 在Xcode Project中创建bridge-header.h文件
  2. 在bridge-Header文件中导入.h文件
  3. 在Build设置中设置bridge-Header的路径。
  4. 清理项目

2

  1. 在项目中创建objective-c文件(它会自动在Build Settings中设置路径)
  2. 在bridge-Header文件中导入.h文件

现在很高兴去谢谢


0
投票

Logans answer工作正常,除了最新的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
    }
}

116
投票

请参阅Apple的Using Swift with Cocoa and Objective-C指南。本指南介绍了如何使用Swift中的Objective-C和C代码,反之亦然,并提供了如何在现有项目中转换项目或混合和匹配Objective-C / C和Swift部件的建议。

编译器自动生成Swift语法,用于调用C函数和Objective-C方法。如文档中所示,此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-ified版本。 (您也可以通过cmd单击Swift文件中的API符号来获取此信息。)iOS 8OS X v10.10 (Yosemite)开发人员库中的所有API参考文档都可以在Objective-C和Swift格式中看到(例如UIView)。


59
投票

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

  1. 通过选择File - > New - > New File - > Objective-C File,将任何Objective-C文件添加到Swift项目中。保存后,Xcode会询问您是否要添加桥接标头。选择“是”。 Gif: adding empty file to project and generating bridging header http://www.derrrick.com/stackoverflow/1-empty-file.gif

简单的步骤:

  1. 出现提示,然后单击确定...如果没有出现,则我们手动创建它,如下所示...从iOS源创建一个头文件并命名为ProjectName-Bridging-Header(示例:Test -Bridging-Header),然后转到Swift编译器代码中的构建设置 - > Objective-C bridge添加Objective-C桥接名称..(Test / Test-Bridging-Header.h)。是的,那是完整的。
  2. (可选)删除您添加的Objective-C文件(在上面的GIF图像中命名为“任何内容”)。你不再需要它了。
  3. 打开桥接头文件 - 文件名的格式为[YourProject] -Bridging-Header.h。它包括Xcode提供的评论。为要包含的Objective-C文件添加一行代码,例如第三方框架。例如,要将Mixpanel添加到项目中,您需要将以下代码行添加到桥接头文件中: #import“Mixpanel.h”
  4. 现在在任何Swift文件中,您都可以使用现有的Objective-C代码,在Swift语法中(在本例中,您可以调用Mixpanel SDK方法等)。您需要熟悉Xcode如何将Objective-C转换为Swift。 Apple's guide是一个快速阅读。或者查看此答案以获得不完整的摘要。

Mixpanel的示例:

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

而已!

注意:如果从项目中删除桥接头文件,请务必进入构建设置并删除“Swift编译器 - 代码生成”下的“Objective-C桥接头”的值。


38
投票

你可以阅读不错的帖子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


24
投票

我写了一个简单的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头放在那里。

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


21
投票

引自documentation

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

import Foundation

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


20
投票

One more thing I would like to add here:

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

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

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

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

你要做的很简单的事情是:

  1. 转到<YOUR-PROJECT>-Bridging-Header文件和
  2. 将语句#import <ObjC_Framework>替换为@import ObjC_Framework

例如:(流行库)

更换

#import <pop/POP.h>

@import pop;

clang import不工作时使用#import


11
投票

对于试图向Swift添加Objective-C库的人来说只是一个注释:你应该在Build Settings - > Linking - > Other Linker Flags中添加-ObjC。


8
投票

创建桥接标头后,转到Build Setting => Search for“Objective-C Bridging Header”。

在下面你会发现“”Objective-C Generated Interface Header Name“文件。

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

示例:在我的情况下:“Dauble-Swift.h”

eEter image description here

© www.soinside.com 2019 - 2024. All rights reserved.