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

  显示原文与译文双语对照的内容

在苹果的新Swift语言中,如何调用 objective-c 代码?

苹果提到,他们可以在一个应用程序中所做的,但这是否意味着一个学术上re-use旧类 co-exist objective-c whilst生成新类在迅速?

推理

objective-c 是platform-independent语言,而Swift是 platform-dependent 。 在swift中编写non-platform-dependent代码( 业务逻辑库) 并不明智。 然而在是( 接口相关的接口) 就是盒完美fine,写作 platform-dependent code. 不是说这是个好主意,但是它绝对是一个有趣

时间:

在Swift中使用 objective-c 类

如果你有一个现有的类,你希望使用,请执行 ** 步 2 然后跳到步骤 5 。 ( 在某些情况下,我必须添加一个显式 #import <Foundation/Foundation.h 到旧的ObjC文件( ** )

步骤 1: 添加 objective-c 实现 -- 。m

.m 文件添加到你的类,并将它的命名为 CustomObject.m

步骤 2: 添加桥接头

添加 .m 文件时,你可能会遇到类似这样的提示:

enter image description here

单击

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

在某些情况下,尤其是在处理ObjC框架,你不显式地添加一个 objective-c 类和Xcode找不到链接器。 在你的项目中的目标的设定诸如so,创建你的.h 文件命名如前所述,在本例中,然后确保你连接它 path:

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"

即使你看不到 file: <#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 someFunction:@"Arg"];
NSLog(@"RetString: %@", retString);

使用纯 Swift objective-c 类

在评论中指出, @TomášLinhart,"objective-c 可访问和可用性, Swift 类必须的后代 @objc objective-c 类或它必须明显。"因为我们的第一个例子是 NSObject的后代,这是编译器自动。 让我们来看一个不是 objective-c 类的子代的示例类。

步骤 1: 创建新的Swift 类

.swift 文件添加到项目中,并将它的命名为 PureSwiftObject.swift

PureSwiftObject.swift 中:


import Foundation

//Note '@objc' prefix
@objc class PureSwiftObject {

 var name: String
 init(name: String) {
 self.name = name
 }

//Needed to add a class level initializer
 class func newInstanceNamed(name: String) -> PureSwiftObject {
 return PureSwiftObject(name: name)
 }

//Just a method for demonstration
 func someMethod() {
 println("Some method ran in pure swift object")
 }
}

为此,我创建了一个名为'newinstancenamed:'的类初始值设定项。 因为此类不再是 NSObject的后代,所以它不再可以访问'分配'或者'新建'。 也许还有另一种方法,但这是我找到的唯一方法。 我在文档中没有找到任何明确提及的内容。 如果你这样做,它与我的方法,请告诉我,我将更新答案符合建议的风格。

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

SomeRandomClass.m 中:


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

( 如果你还没有这么做的话)

步骤 3: 使用你的纯 Swift 类


PureSwiftObject * pureSwiftObject = [PureSwiftObject newInstanceNamed:@"Janet"];
NSLog(@"PureSwiftNamed: %@", pureSwiftObject.name);
[pureSwiftObject someMethod];

注:

1 CodeCompletion没有像我想的那样精确。 在我的系统,运行快速构建w/"cmd + R"似乎帮助 Swift 找到一些Objc代码,反之亦然。

2.如果你 .swift 文件添加到一个老项目并得到错误: dyld: Library not loaded: @rpath/libswift_stdlib_core.dylib ,尝试完全重新启动 Xcode 。

使用与 Cocoa Swift 和 objective-c, 看到导轨上的苹果,以 在现有project,本指南涵盖了如何使用从 Swift ObjC和C 代码,反之亦然,并具有建议,说明如何将一个项目或者混合和匹配 ObjC/C 和 Swift 部分。

编译器会自动生成 Swift 语法来调用C 函数和ObjC方法。 在文档中看到,这个 ObjC:


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

变成这个 Swift:


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

Xcode也做这个翻译的就往—打开快速编辑一个 Swift 文件并键入一个ObjC类名称时,你可以使用,它将带你到一个Swift-ified版本的类的头部。 ( 你也可以通过cmd-clicking在 Swift 文件中获取API符号。iOS 8OS X 开发人员库中的所有API参考文档都可以在ObjC和 Swift 表单中看到,例如。UIView ) 。

你可以阅读这篇漂亮的帖子 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)
 })

还可以查看的文档,使用 Swift 和 Cocoa 和 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 头放在那里。

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

来自文档的引用:

任何可以作为模块访问的objective-c 框架( 或者C 库) 都可以直接导入 Swift 。 这包括所有 objective-c 系统frameworks—such作为基础,UIKit和 SpriteKit—as,以及与系统提供的公共C 库。 例如要导入基础,只需将这个导入语句添加到你正在使用的Swift 文件的顶部:

import Foundation

这个导入使所有的基础 APIs—including NSDate,NSURL,NSMutableData和它们的所有方法,属性和categories—directly都可以在Swift中使用。

在一个 Swift project,以下是逐步说明如何使用 objective-c 代码

  1. 通过选择文件> 新> 新文件> objective-c 文件向 Swift 项目添加任何 objective-c 文件。 在保存之前,XCode会询问你是否希望添加一个桥接头 。 选择''。 Gif: adding empty file to project and generating bridging header

  2. ( 可选) 删除你添加( 命名名"什么"在上面的gif中) objective-c 文件,你不需要它了

  3. 打开桥接头文件 --窗体的文件名是 [YourProject] -Bridging-Header.h 。 它包含一个Xcode-provided注释。 为 objective-c 添加一行代码文件你想包括,比如 3 rd-party框架。 例如要将Mixpanel添加到项目中,需要将以下代码行添加到桥接头 file:

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

Mixpanel示例:


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

就是这样!

注意:如果你把连接头文件从项目,一定要进入构建设置和清除" objective-c 桥接头""快速编译器- 代码生成"下的值。

...