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中编写如下代码:
import Foundation ①
@objc class SwiftObject: NSObject { ②
func sayHello(greeting : String, withName name : String) -> String { ③
var string = "Hi," + name
string += greeting
return string
}
}
上述代码第①行引入了Foundation框架的头文件。第②行代码定义SwiftObject
类,SwiftObject
类继承自NSObject
类。另外,我们在类前面声明为@objc
,@objc
所声明的类能够被Objective-C访问,@objc
还可以修饰属性。
第③行代码定义了sayHello
方法,它有两个参数,第一个参数不需要指定外部参数名,第二个参数(除了第一个以后所有的参数)需要指定外部参数名,例如withName
是name
参数的外部参数名。这是为了方便在Objective-C中调用。
下面看Objective-C端的代码,main.m文件代码如下:
#import <Foundation/Foundation.h>
#import "HelloWorld-swift.h" ①
int main(intargc, const char * argv[]) {
SwiftObject sobj = [[SwiftObject alloc] init]; ②
NSString hello = [sobj sayHello:@"Good morning" withName:@"Tony"]; ③
NSLog(@"%@",hello); ④
return 0;
}
上述代码第①行引入头文件HelloWorld-swift.h,它是Objective-C调用Swift对象所必需的,它的命名规则是“<工程名>-swift.h”。
第②行代码实例化SwiftObject
对象,SwiftObject
是Swift中定义的类。第③行代码调用SwiftObject
的sayHello
方法,它在Objective-C中被调用时的方法和参数命名与SwiftObject
的方法和参数之间的对应关系如图18-15所示。
图 18-15 Swift与Objective-C调用方法和参数对应关系
第④行代码NSLog(@"%@",hello)
用于输出结果,输出结果如下:
2014-07-05 14:25:43.879 HelloWorld[3266:303] Hi,TonyGood morning
这样就实现了在Objective-C中调用Swift代码,我们可以借助于这样的调用充分利用已有的Swift文件,减少重复编写代码,提高工作效率。