如何从Swift调用Objective-C代码

Dav*_*der 936 objective-c swift

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

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

推理

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

Log*_*gan 1354

在Swift中使用Objective-C类

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

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

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

第2步:添加桥接标头

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

在此输入图像描述

单击!

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

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

在此输入图像描述

注意

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

$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h
Run Code Online (Sandbox Code Playgroud)

第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
Run Code Online (Sandbox Code Playgroud)

CustomObject.m

#import "CustomObject.h"

@implementation CustomObject 

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

@end
Run Code Online (Sandbox Code Playgroud)

第5步:向Bridging-Header添加类

YourProject-Bridging-Header.h:

#import "CustomObject.h"
Run Code Online (Sandbox Code Playgroud)

第6步:使用您的对象

SomeSwiftFile.swift:

var instanceOfCustomObject: CustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
println(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()
Run Code Online (Sandbox Code Playgroud)

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

在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
    }   
}
Run Code Online (Sandbox Code Playgroud)

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

SomeRandomClass.m:

#import "<#YourProjectName#>-Swift.h"
Run Code Online (Sandbox Code Playgroud)

文件:<#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);
Run Code Online (Sandbox Code Playgroud)

注意:

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

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

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

  • 你是对的.如果不使用Cocoa对象,则只需指定它.***为了在Objective-C中可访问和使用,Swift类必须是Objective-C类的后代,或者必须标记为@objc.*** (29认同)
  • 如果将Objective C框架导入Swift,请确保将Obj C框架所依赖的所有框架导入到您的项目中(在Build Phases - > Link Binary With Libraries中),然后将#import'添加到前缀头文件中,必须在构建设置中添加到项目中(在"前缀标题"字段中).这包括UIKit和Foundation等框架,即使这些框架已经在Swift中使用过.这让我吵了几个小时,似乎没有人记录这些步骤. (6认同)
  • 重要的是,您需要使用@objc注释方法,否则将无法从Objective-C中看到Swift方法. (5认同)
  • @MarkusRautopuro - 从这里得到它:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_75" (2认同)
  • 另请参见:WWDC 2014 Session 406:将Swift与Objective-C集成 (2认同)
  • @lee - 你能进入你的构建设置并确保你的`Product Module Name`符合你的期望,语法真的是`#import"ProductModuleName-Swift.h`,它只是默认为项目名称而且大多数人都不喜欢改变它. (2认同)
  • 谢谢@Logan这对我有用,但我注意到的唯一不同的是,当你添加.m或.h文件时,xcode 7.3没有弹出来创建桥接头,你必须手动转到Build Settings并执行它或者我的项目设置可能有问题:). (2认同)

ric*_*ter 116

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

编译器自动生成Swift语法,用于调用C函数和Objective-C方法.如文档中所示,此Objective-C:

UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
Run Code Online (Sandbox Code Playgroud)

变成这个Swift代码:

let myTableView: UITableView = UITableView(frame: CGRectZero, style: .Grouped)
Run Code Online (Sandbox Code Playgroud)

Xcode也可以动态执行此转换 - 您可以在编辑Swift文件时使用Open Quickly并键入Objective-C类名称,它将带您进入类标题的Swift-ified版本.(您也可以通过cmd单击Swift文件中的API符号来获取此信息.)并且在Objective-C和Swift中都可以看到iOS 8OS X v10.10(Yosemite)开发人员库中的所有API参考文档.表格(例如UIView).

  • **Apple文档的直接链接**如何在现有项目中集成Swift:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/ DOC/UID/TP40014216-CH10-XID_75 (2认同)

小智 59

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

  1. 通过选择File - > New - > New File - > Objective-C File,将任何Objective-C文件添加到Swift项目中.保存后,Xcode会询问您是否要添加桥接标头.选择" ".Gif:将空文件添加到项目并生成桥接头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的指南快速阅读.或者查看此答案以获得不完整的摘要.

Mixpanel的示例:

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

而已!

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


Jak*_*Lin 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)
  })
Run Code Online (Sandbox Code Playgroud)

另请参阅Apple的文档使用Swift与Cocoa和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头放在那里.

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


Ger*_*osi 21

文档中引用:

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

import Foundation

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


Kam*_*pai 21

我还想在这里添加一件事:

我非常感谢@ 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>
Run Code Online (Sandbox Code Playgroud)

@import pop;
Run Code Online (Sandbox Code Playgroud)

clang import#import不工作时使用.


yoA*_*ex5 17

混合 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
Run Code Online (Sandbox Code Playgroud)

Swift 消费者,Objective-C 生产者

  1. 添加新的头文件.h和实现.m文件 - Cocoa 类文件(Objective-C)
    例如<MyFileName>.h<MyFileName>.m

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

    • <target_name>-Bridging-Header.h会自动生成
    • 构建设置 -> Objective-C 桥接标头(SWIFT_OBJC_BRIDGING_HEADER)
  3. 将类添加到 Bridging-Header
    <target_name>-Bridging-Header.h添加一行#import "<MyFileName>.h"

之后您可以使用 from Swift Objective-C's MyFileName.h,MyFileName.m

PS 如果您应该将现有的Objective-C 文件添加到 Swift 项目中,请Bridging-Header.h预先添加并导入它

Objective-C 消费者,Swift 生产者

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

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

  3. 通过[About]公开 Swift 代码@objc

之后您就可以使用Objective-C Swift's <MyFileName>.swift

[<产品名称>-Swift.h 文件未找到]

不同的目标 [.modulemap][umbrella.h]用于为 Swift 公开 Objective-C。以及Swift.h为 Objective-C 公开 Swift 代码

[词汇]


dav*_*d72 11

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


Avi*_*are 8

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

在下面你会发现""Objective-C Generated Interface Header Name"文件.

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

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

eEter图像描述在这里


小智 7

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

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


ARG*_*Geo 7

在 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:如果您第一次将新的 Objective-C 文件添加到 Swift 项目中,Xcode 会询问您:

Would you like to configure an Objective-C bridging header

在此输入图像描述

步骤_04:选择选项:

Create Bridging Header

Step_05:将生成相应的文件,文件名:

Objc-Bridging-Header.h

在此输入图像描述

Step_06: 现在,您需要在桥头中设置桥文件路径。在项目导航器中单击项目名称objc,然后选择:

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

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

在此输入图像描述

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

#import "SpecialObjcFile.m"
Run Code Online (Sandbox Code Playgroud)

这里有一个内容SpecialObjcFile.m

#import <Foundation/Foundation.h>

@interface Person: NSObject {
@public
    bool busy;
}
@property
    bool busy;
@end
Run Code Online (Sandbox Code Playgroud)

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

override func viewDidLoad() {
    super.viewDidLoad()
    let myObjcContent = Person()
    print(myObjcContent.busy)
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述 在此输入图像描述


Nis*_*ish 6

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


归档时间:

查看次数:

274669 次

最近记录:

6 年,1 月 前