精校版usingswiftwithcocoaandobjectivecmixandmatch.docx
《精校版usingswiftwithcocoaandobjectivecmixandmatch.docx》由会员分享,可在线阅读,更多相关《精校版usingswiftwithcocoaandobjectivecmixandmatch.docx(7页珍藏版)》请在冰点文库上搜索。
精校版usingswiftwithcocoaandobjectivecmixandmatch
[精校版]usingswiftwithcocoaandobjectivecmixandmatch
Swift系列文章由CocoaChina翻译小组翻译自苹果的官方文档:
UsingSwiftwithCocoaandObjective-C--MixandMatch--SwiftandObjective-CintheSameProject。
本篇译者:
haolloyin(github主页),敬请勘误,欢迎在CocoaChinagithub主页参看更多文章。
Swift与Objective-C的兼容能力允许你在同一个工程中同时使用两种语言。
你可以用这种叫做“mixandmatch”的特性来开发基于混合语言的应用。
使用Swfit的最新特性--“mixandmatch”,你可以实现应用的一部分功能,并无缝地并入已有的Objective-C的代码中。
MixandMatch概述
Swift与Objective-C文件可以在一个工程中并存,不管这个工程原本是基于Objective-C还是Swift。
你可以直接往现有工程中简单地添加另一种语言的文件。
这种自然的工作流使得创建混合语言的应用或frameworktarget,与用单独一种语言时一样简单。
编写混合语言的工作流程只有一点点区别,这取决于你是在写应用还是写框架。
下面描述了用两种语言在一个target中导入模型的情况,后续章节会有更多细节。
在同一个AppTarget中进行代码导入
如果你在写混合语言的应用,可能需要用Swift代码访问Objective-C代码,或者反之。
本章描述的流程适用于non-frameworktarget。
将Objective-C导入Swift
要在同一个apptarget中导入Objective-C文件供Swift使用,你需要依赖Objective-C的桥接头文件(Objective-Cbridgingheader)来暴露给Swift。
当你添加Swift文件到现有的Objective-C应用时,Xcode会自动创建这些头文件,反之亦然。
如果你同意,Xcode会在源文件创建的同时生成头文件,并用product的模块名加上-Bridging-Header.h命名。
关于product的模块名,详见NamingYourProductModule。
你应该编辑这个头文件来对Swift暴露出Objective-C代码。
在同一target中将Objective-C代码导入到Swift中
1.在Objective-C桥接头文件中,导入任何你想暴露给Swift的头文件,例如:
OBJECTIVE-C
#import"XYZCustomCell.h"#import"XYZCustomView.h"#import"XYZCustomViewController.h"
2.在BuildSettings中,确保Objective-C桥接头文件的buildsetting是基于Swfit编译器,即CodeGeneration含有头文件的路径。
这个路径必须是头文件自身的路径,而不是它所在的目录。
这个路径应该是你工程的相对路径,类似Info.plist在BuildSettings中指定的路径。
在大多数情况下,你不需要修改这个设置。
在这个桥接头文件中列出的所有公开的Objective-C头文件都会对Swift可见。
之后当前target的所有Swift文件都可以使用这些头文件中的方法,不需要任何import语句。
用Swift语法使用这些Objective-C代码,就像使用系统自带的类一样。
SWIFT
letmyCell=XYZCustomCell()myCell.subtitle="Acustomcell"
将Swift导入Objective-C
向Objective-C中导入Swift代码时,你依赖Xcode生成的头文件来向Objective-C暴露Swift代码。
这个自动生成Objective-C头文件,声明了target中所有Swift代码中定义的接口。
可以把这个Objective-C头文件看作Swift代码的umbrellaheader。
它以product模块名加-Swift.h来命名。
关于product的模块名,详见NamingYourProductModule。
你不需要做任何事情来生成这个头文件,只需要将它导入到你的Objective-C代码来使用它。
注意这个头文件中的Swift接口包含了它所使用到的所有Objc类型。
如果你在Swift代码中使用你自己的Objective-C类型,确保先将对应的Objc头文件导入到你的Swift代码中,然后才将Swift自动生成的头文件导入到Objc.m源文件中来访问Swift代码。
在同一target中将Swift代码导入到Objective-C中
在相同target的Objc.m源文件中,用下面的语法来导入Swift代码:
OBJECTIVE-C
#import“ProductModuleName-Swift.h”
target中任何Swift文件将会对Objc.m文件可见,包括这个import语句。
关于在Objc代码中使用Swift代码,详见UsingSwiftfromObjective-C。
在同个FrameworkTarget中导入代码
如果你在写一个混合语言的框架,可能会从Swift代码访问Objc代码,或者反之。
将Objc导入Swift
要将一些Objc文件导入到同个框架target的Swift代码中去,你需要将这些文件导入到Objc的umbrellaheader来供框架使用。
在同一framework中将Objective-C代码导入到Swift中
确保将框架target的BuildSettings>Packaging>DefinesModule设置为Yes。
然后在你的umbrellaheader头文件中导入你想暴露给Swift访问的Objc头文件,例如:
OBJECTIVE-C
#import<XYZ/XYZCustomCell.h>#import<XYZ/XYZCustomView.h>#import<XYZ/XYZCustomViewController.h>
Swift将会看到所有你在umbrellaheader中公开暴露出来的头文件,框架target中的所有Swift文件都可以访问你Objc文件的内容,不需要任何import语句。
SWIFT
letmyCell=XYZCustomCell()myCell.subtitle="Acustomcell"
将Swift导入Objc
要将一些Swift文件导入到同个框架的target的Objc代码去,你不需要导入任何东西到umbrellaheader文件,而是将Xcode为你的Swift代码自动生成的头文件导入到你的Obj.m源文件去,以便在Objc代码中访问Swift代码。
在同一framework中将Swift代码导入到Objective-C中
1.确保将框架target的BuildSettings>Packaging中的DefinesModule设置为Yes。
用下面的语法将Swift代码导入到同个框架target下的Objc.m源文件去。
OBJECTIVE-C
#import<ProductName/ProductModuleName-Swift.h>
这个import语句所包含的Swift文件都可以被同个框架target下的Objc.m源文件访问。
关于在Objc代码中使用Swift代码,详见UsingSwiftfromObjective-C。
导入外部Framework
你可以导入外部框架,不管这个框架是纯Objc,纯Swift,还是混合语言的。
import外部框架的流程都是一样的,不管这个框架是用一种语言写的,还是包含两种语言。
当你导入外部框架时,确保BuildSetting>Pakaging>DefinesModule设置为Yes。
用下面的语法将框架导入到不同target的Swift文件中:
SWIFT
importFrameworkName
用下面的语法将框架导入到不同target的Objc.m文件中:
OBJECTIVE-C
@importFrameworkName;
在Objective-C中使用Swift
当你将Swift代码导入Objc文件之后,用普通的Objc语法使用Swift类。
OBJECTIVE-C
MySwiftClass*swiftObject=[[MySwiftClassalloc]init];[swiftObjectswiftMethod];
Swift的类或协议必须用@objcattribute来标记,以便在Objc中可访问。
这个attribute告诉编译器这个Swift代码可以从Objc代码中访问。
如果你的Swift类是Objc类的子类,编译器会自动为你添加@objcattribute。
详见SwiftTypeCompatibility。
你可以访问Swift类或协议中用@objcattribute标记过东西,只要它和Objc兼容。
不包括一下这些Swift独有的特性:
Generics-范型
Tuples-元组
EnumerationsdefinedinSwift-Swift中定义的枚举
StructuresdefinedinSwift-Swift中定义的结构体
Top-levelfunctionsdefinedinSwift-SwiftSwift中定义的顶层函数
GlobalvariablesdefinedinSwift-Swift中定义的全局变量
TypealiasesdefinedinSwift-Swift中定义的类型别名
Swift-stylevariadics
Nestedtypes-嵌套类型
Curriedfunctions-柯里化后的函数
例如带有范型类型作为参数,或者返回元组的方法不能在Objective-C中使用。
为了避免循环引用,不要将Swift代码导入到Objective-C头文件中。
但是你可以在Objective-C头文件中前向声明(forwarddeclare)一个Swift类来使用它,然而,注意不能在Objective-C中继承一个Swift类。
在Objective-C头文件中引用Swift类
这样前向声明Swift类:
OBJECTIVE-C
//MyObjcClass.h@classMySwiftClass;@interfaceMyObjcClass:
NSObject-(MySwiftClass*)returnSwiftObject;/*...*/@end
ProductModule命名
Xcode为Swift代码生成的头文件的名称,以及Xcode创建的Objc桥接头文件名称,都是从你的product模块名生成的。
默认你的product模块名和product名一样。
然而,如果你的product名有特殊字符(nonalphanumeric,非数字、字母的字符),例如点号,那么它们会被下划线(_)替换之后作为你的product模块名。
如果product名以数字开头,那么第一个数字会用下划线替换掉。
你可以给product模块名提供一个自定义的名称,Xcode会用这个名称来命名桥接的和自动生成的头文件。
你只需要在修改在buildsetting中的ProductModuleName即可。
故障排除和提醒
·把Swift和Objc文件看作相同的代码集合,并注意命名冲突;
·如果你用框架,确保BuildSetting>Pakaging>DefinesModule设置为Yes;
·如果你使用Objc桥接头文件,确保在BuildSettings中Objc桥接头文件的buildsetting是基于Swfit编译器,即CodeGeneration含有头文件的路径。
这个路径必须是头文件自身的路径,而不是它所在的目录。
·Xcode使用你的product模块名,而不是target名来命名Objc桥接头文件和为Swift自动生成的头文件。
详见NamingYourProductModule;
·为了在Objc中可用,Swift类必须是Objc类的子类,或者用@objc标记;
·当你将Swift导入到Objc中时,记住Objc不会将Swift独有的特性翻译成Objc对应的特性。
详见列表UsingSwiftfromObjective-C;
·如果你在Swift代码中使用你自己的Objc类型,确保先将对应的Objc头文件导入到你的Swift代码中,然后才将Swift自动生成的头文件import到Objc.m源文件中来访问Swift代码。
本章由CocoaChina的翻译小组成员haolloyin(github主页)翻译,转载请注明出处和译者信息,拒绝商业之用。