18.3 Objective-C调用Swift

如果已经有了一个老的iOS应用,它是使用Objective-C编写的,而它的一些新功能需要采用Swift来编写,这时就可以从Objective-C调用Swift。

Objective-C调用Swift时不需要桥接头文件,而是需要Xcode生成的头文件。这种文件由Xcode生成,不需要我们维护,对于开发人员也是不可见的。如图18-7所示,它能够将Swift中的类暴露给Objective-C,它的命名是:<工程名>-swift.h。我们需要将该头文件引入到Objective-C文件中,而且Swift中的类需要声明为@objc

{%}

图 18-7 Objective-C调用Swift与Xcode生成头文件

18.3.1 创建Objective-C的iOS工程

为了能够更好地介绍混合搭配调用,我们首先创建一个Objective-C的iOS工程。

启动Xcode 6,然后单击File→New→Project菜单,在打开的Choose a template for your new project界面中选择“iOS→Application→Single View Application”工程模板(如图18-8所示)。

{%}

图 18-8 选择工程模板

接着单击“Next”按钮,随即出现如图18-9所示的界面。

{%}

图 18-9 新工程中的选项

在Product Name中输入“HelloWorld”,在Language中选择Objective-C,其他的项目可以结合自己的实际情况输入内容。相关的工程选项设置完成后,单击“Next”按钮,后面的步骤与18.2.1节类似,在此不再赘述。

创建成功后的界面如图18-10所示,然后选择图18-10中的5个文件删除,文件删除后工程中的main.m文件会有编译错误,如图18-11所示,这个错误我们先不用考虑它,我们会在下一节修改main.m文件。

{%}

图 18-10 新建的Objective-C工程

{%}

图 18-11 main.m编译错误

18.3.2 在Objective-C工程中添加Swift类

我们刚刚创建了Objective-C的工程,需要添加Swift类到工程中。具体过程是,右键选择HelloWorld组,选择菜单中的“New File…”弹出新建文件模板对话框。如图18-12所示,选择iOS X→Source→Cocoa Touch Class。

注意 这里我们并没有选择Swift File,是因为需要创建的Swift类是基于Cocoa Touch框架的。

{%}

图 18-12 新建文件模板

接着单击“Next”按钮,随即出现如图18-13所示的界面。在Class中输入“SwiftObject”,在Subclass of中选择NSObject,这个选项可以让生成的Swift类继承于NSObject。在Language中选择Swift。

{%}

图 18-13 新建Swift类

相关选项设置完成后,单击“Next”按钮,进入保存文件界面,根据提示选择存放文件的位置,然后单击“Create”按钮创建Swift类。如果工程中没有桥接头文件,在创建过程中,Xcode也会提示我们是否添加桥接头文件,我们需要选择添加。

以上操作成功后在Xcode工程中生成了SwiftObject.swift文件,Xcode界面如图18-14所示。

{%}

图 18-14 Xcode界面

18.3.3 调用代码

Swift的SwiftObject创建完成后,我们会在Xcode工程中看到新增加的SwiftObject.swift文件。我们在SwiftObject.swift中编写如下代码:

  1. import Foundation
  2. @objc class SwiftObject: NSObject {
  3. func sayHello(greeting : String, withName name : String) -> String {
  4. var string = "Hi," + name
  5. string += greeting
  6. return string
  7. }
  8. }

上述代码第①行引入了Foundation框架的头文件。第②行代码定义SwiftObject类,SwiftObject类继承自NSObject类。另外,我们在类前面声明为@objc@objc所声明的类能够被Objective-C访问,@objc还可以修饰属性。

第③行代码定义了sayHello方法,它有两个参数,第一个参数不需要指定外部参数名,第二个参数(除了第一个以后所有的参数)需要指定外部参数名,例如withNamename参数的外部参数名。这是为了方便在Objective-C中调用。

下面看Objective-C端的代码,main.m文件代码如下:

  1. #import <Foundation/Foundation.h>
  2. #import "HelloWorld-swift.h" ①
  3. int main(intargc, const char * argv[]) {
  4. SwiftObject sobj = [[SwiftObject alloc] init];
  5. NSString hello = [sobj sayHello:@"Good morning" withName:@"Tony"];
  6. NSLog(@"%@",hello);
  7. return 0;
  8. }

上述代码第①行引入头文件HelloWorld-swift.h,它是Objective-C调用Swift对象所必需的,它的命名规则是“<工程名>-swift.h”。

第②行代码实例化SwiftObject对象,SwiftObject是Swift中定义的类。第③行代码调用SwiftObjectsayHello方法,它在Objective-C中被调用时的方法和参数命名与SwiftObject的方法和参数之间的对应关系如图18-15所示。

{%}

图 18-15 Swift与Objective-C调用方法和参数对应关系

第④行代码NSLog(@"%@",hello)用于输出结果,输出结果如下:

  1. 2014-07-05 14:25:43.879 HelloWorld[3266:303] Hi,TonyGood morning

这样就实现了在Objective-C中调用Swift代码,我们可以借助于这样的调用充分利用已有的Swift文件,减少重复编写代码,提高工作效率。