如何从Swift调用Objective-C代码

时间:2014-06-02 20:05:43

标签: objective-c swift

在Apple的新Swift语言中,如何调用Objective-C代码?

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

推理

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

17 个答案:

答案 0 :(得分:1307)

在Swift中使用Objective-C类

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

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

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

第2步:添加桥接标题

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

Enter image description here

点击

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

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

Enter image description here

注意

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

$(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 = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
println(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()

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

在Objective-C中使用Swift类

第1步:创建新的Swift类

.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
    }   
}

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

// 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版本中重新启用此功能,答案将相应更新。

答案 1 :(得分:115)

请参阅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符号来获取此信息。)在{-3}}和iOS 8开发人员库中的所有API参考文档都可在Objective-C和Swift中看到表格(例如OS X v10.10 (Yosemite))。

答案 2 :(得分:57)

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

  1. 通过选择文件 - &gt;将任何Objective-C文件添加到Swift项目;新 - &gt;新文件 - &gt; Objective-C文件。保存后, Xcode会询问您是否要添加桥接标头。选择&#39;。 Gif: adding empty file to project and generating bridging header http://www.derrrick.com/stackoverflow/1-empty-file.gif
  2. 简单的步骤:

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

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

    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快速阅读。或者查看此答案以获得不完整的摘要。

    5. Mixpanel的例子:

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

      那就是它!

      注意:如果从项目中删除桥接头文件,请务必进入构建设置并删除&#34; Objective-C桥接头&#34;在&#34; Swift编译器 - 代码生成&#34;。

答案 3 :(得分:36)

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

答案 4 :(得分:23)

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

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

答案 5 :(得分:20)

来自documentation

的引用
  

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

     

import Foundation

     

此导入使所有Foundation API - 包括NSDate,NSURL,   NSMutableData,以及它们的所有方法,属性和   类别 - 可直接在Swift中使用。

答案 6 :(得分:19)

我想在此处补充一点:

我非常感谢@ 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
  3. 例如:(流行图书馆)

    替换

    #import <pop/POP.h>
    

    @import pop;
    

    clang import无效时使用#import

答案 7 :(得分:10)

对于想要向Swift添加Objective-C库的人员,请注意:您应该在构建设置中添加 -ObjC - &gt; 链接 - &gt; 其他链接标记

答案 8 :(得分:8)

创建桥接标头后,转到Build Setting =&gt;搜索“Objective-C Bridging Header”。

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

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

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

eEter image description here

答案 9 :(得分:3)

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

答案 10 :(得分:3)

enter image description here我在github上添加了一个项目,其中包含一些来自swift的调用目标c代码的小样本。

Call ObjectiveC class from swift

答案 11 :(得分:1)

在Xcode 10.1的Swift 4.2.1项目中,您可以轻松添加Objective-C文件。按照以下步骤将Objective-C文件桥接到Swift项目。

Step_01:使用Swift语言创建新的Xcode项目:

if __name__=='__main__': while(True): try: print "***********" print "1. Continuous" print "2. Single Step" print "***********" try: choice = int(raw_input('Choose a number between 1 & 2: ')) number = choice move_group_python_interface() except ValueError: print "ERROR! Choose a number between 1 and 2" except rospy.ROSInterruptException: break &gt; File&gt; New&gt; Project

Step_02:在Swift项目中添加新的Objective-C文件:

objc&gt; File&gt; New&gt; File...&gt; macOS

Step_03:如果你第一次在Swift项目中添加一个新的Objective-C文件,Xcode会问你:

Objective-C File

enter image description here

Step_04:选择选项:

Would you like to configure an Objective-C bridging header

Step_05:将生成一个名称为

的相应文件

Create Bridging Header

enter image description here

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

objc&gt; Build Settings&gt; Objective-C Bridging Header

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

enter image description here

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

Objc-Bridging-Header.h

这里的内容为#import "SpecialObjcFile.m"

SpecialObjcFile.m

Step_09:现在在你的Swift文件中,你可以使用Objective-C类:

#import <Foundation/Foundation.h>

@interface Person: NSObject {
@public
    bool busy;
}
@property
    bool busy;
@end

enter image description here enter image description here

答案 12 :(得分:0)

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

<强> 1

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

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

答案 13 :(得分: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. 在“构建设置”的“ Swift编译器-代码生成”中,确保“ Objective-C桥接头”构建设置具有桥接头文件的路径。该路径应相对于您的项目,类似于在“构建设置”中指定Info.plist路径的方式。在大多数情况下,您无需修改​​此设置。

桥接标头中列出的任何公共Objective-C标头对Swift都是可见的。

答案 14 :(得分: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
    }
}

答案 15 :(得分:0)

迅速的消费者,Objective-C生产者

  1. 添加头文件.h和实现文件.m-可可类文件
    例如MyFileName

  2. 配置桥接头
    当您看到Would you like to configure an Objective-C bridging header时,请点击-是

  3. 将类添加到Bridging-Header
    Project-Bridging-Header.h中添加一行#import "<MyFileName>.h"

Objective-C消费者,Swift生产者

  1. 添加一个<MyFileName>.swift并扩展NSObject

  2. 将Swift文件导入到ObjC类中
    #import "<#YourProjectName#>-Swift.h"添加到您的Objective-C文件中

  3. 标记公共Swift代码[@objc and @objcMembers]

答案 16 :(得分:0)

制作NSObject的任何Swift类子类也很有意义,我更喜欢使用任何Swift类在Objective-C类中看到:

@objc(MySwiftClass)
@objcMembers class MySwiftClass {...}