Using Swift with Cocoa and Objective-C--在同个project中使用Swift和在同个project中

http://www.cocoachina.com/newbie/basic/2014/0605/8688.htmlhtml



Swift系列文章由CocoaChina翻译小组翻译自苹果的官方文档: Using Swift with Cocoa and Objective-C--Swift and Objective-C in the Same Project。本篇译者:haolloyin( github主页),敬请勘误。

Swift与Objective-C的兼容能力赞成你在同一个project中同一时候使用两种语言。你可以用这样的叫作“mix and match”的特性来开发基于混合语言的应用。使用Swfit的最新特性--“mix and match”。你可以实现应用的一部分功能,并没有缝地并入已有的Objective-C的代码中。

 
Mix and Match 概述

Swift与Objective-C文件可以在一个project中并存,不管这个project本来是基于Objective-C仍是Swift。

你可以直接往现有project中简单地加入还有一种语言的文件。这样的天然的工做流使得建立混合语言的应用或framework target,与用单独一种语言时同样简单。ios

 
编写混合语言的工做流程仅仅有一点点差异。这取决于你是在写应用仍是写框架。如下描写叙述了用两种语言在一个target中导入模型的状况,兴许章节会有不少其它细节。

在同一个App Target中进行代码导入

假设你在写混合语言的应用,可能需要用Swift代码訪问Objective-C代码。或者反之。本章描写叙述的流程适用于non-framework target。
 
将Objective-C导入Swift
要在同一个app target中导入Objective-C文件供Swift使用,你需要依赖Objective-C的桥接头文件(Objective-C bridging header)来暴露给 Swift。当你加入 Swift 文件到现有的Objective-C应用时,Xcode 会本身主动建立这些头文件,反之亦然。

假设你容许,Xcode 会在源文件建立的同一时候生成头文件,并用product的模块名加上 -Bridging-Header.h命名。关于 product 的模块名,详见 Naming Your Product Module。
 
你应该编辑这个头文件来对Swift暴露出Objective-C代码。
 
To import Objective-C code into Swift from the same target
 
1.在Objective-C桥接头文件里,导入不论什么你想暴露给 Swift 的头文件。好比:
OBJECTIVE-C
   
   
   
   
  1. #import "XYZCustomCell.h" 
  2. #import "XYZCustomView.h" 
  3. #import "XYZCustomViewController.h" 
2.在Build Settings中,确保Objective-C桥接头文件的build setting是基于 Swfit 编译器,即Code Generation 含有头文件的路径。

这个路径必须是头文件自身的路径。而不是它所在的文件夹。git

 
这个路径应该是你project的相对路径,相似 Info.plist 在 Build Settings 中指定的路径。在大多数状况下,你不需要改动这个设置。
 
在这个桥接头文件里列出的所有公开的Objective-C 头文件都会对 Swift 可见。

以后当前 target 的所有 Swift 文件都可以使用这些头文件里的方法,不需要不论什么import语句。github

用 Swift 语法使用这些Objective-C代码,就像使用系统自带的类同样。swift

SWIFT
   
   
   
   
  1. let myCell = XYZCustomCell() 
  2. myCell.subtitle = "A custom cell" 
将 Swift 导入Objective-C
向Objective-C中导入Swift代码时,你依赖 Xcode 生成的头文件来向Objective-C暴露 Swift 代码。这个本身主动生成Objective-C头文件,声明了target 中所有 Swift 代码中定义的接口。可以把这个Objective-C头文件看做 Swift 代码的umbrella header。

它以 product 模块名加 -Swift.h 来命名。关于 product 的模块名,详见 Naming Your Product Module。app

 
你不需要作不论什么事情来生成这个头文件。仅仅需要将它导入到你的Objective-C代码来使用它。注意这个头文件里的 Swift 接口包括了它所使用到的所有 Objc 类型。

假设你在 Swift 代码中使用你本身的Objective-C类型,确保先将相应的 Objc 头文件导入到你的 Swift 代码中,而后才将 Swift 本身主动生成的头文件导入到 Objc .m 源文件里来訪问 Swift 代码。框架

 
To import Swift code into Objective-C from the same target
 
在一样 target 的 Objc .m 源文件里。用如下的语法来导入Swift 代码:
OBJECTIVE-C
   
   
   
   
  1.   
  2. #import “ProductModuleName-Swift.h” 
target 中不论什么 Swift 文件将会对 Objc .m 文件可见,包含这个 import 语句。

关于在 Objc 代码中使用 Swift 代码。详见 Using Swift from Objective-C。ide


在同个Framework Target中导入代码

假设你在写一个混合语言的框架,可能会从 Swift 代码訪问 Objc 代码。或者反之。

 
将 Objc 导入 Swift
要将一些 Objc 文件导入到同个框架 target 的 Swift 代码中去。你需要将这些文件导入到 Objc 的  umbrella header  来供框架使用。
 
To import Objective-C code into Swift from the same framework
 
确保将框架 target 的  Build Settings > Packaging > Defines Module  设置为  Yes 。而后在你的  umbrella header  头文件里导入你想暴露给 Swift 訪问的 Objc 头文件,好比:
OBJECTIVE-C
   
   
   
   
  1. #import <XYZ/XYZCustomCell.h> 
  2. #import <XYZ/XYZCustomView.h> 
  3. #import <XYZ/XYZCustomViewController.h> 
 
Swift 将会看到所有你在  umbrella header  中公开暴露出来的头文件,框架 target 中的所有 Swift 文件都可以訪问你 Objc 文件的内容,不需要不论什么 import 语句。

SWIFT
   
   
   
   
  1. let myCell = XYZCustomCell() 
  2. myCell.subtitle = "A custom cell" 
 
 
将 Swift 导入 Objc
要将一些 Swift 文件导入到同个框架的 target 的 Objc 代码去,你不需要导入不论什么东西到umbrella header文件,而是将 Xcode 为你的Swift代码本身主动生成的头文件导入到你的 Obj .m 源文件去。以便在 Objc 代码中訪问 Swift 代码。
 
To import Swift code into Objective-C from the same framework
 
1.确保将框架target 的 Build Settings > Packaging  中的  Defines Module  设置为  Yes 。用如下的语法将 Swift 代码导入到同个框架 target 下的 Objc .m 源文件去。
OBJECTIVE-C
   
   
   
   
  1. #import <ProductName/ProductModuleName-Swift.h> 
这个 import 语句所包括的 Swift 文件都可以被同个框架 target 下的 Objc .m 源文件訪问。关于在 Objc 代码中使用 Swift 代码。详见 Using Swift from Objective-C。

导入外部 Framework

你可以导入外部框架,不管这个框架是纯 Objc,纯 Swift。仍是混合语言的。

import 外部框架的流程都是同样的,不管这个框架是用一种语言写的,仍是包括两种语言。函数

当你导入外部框架时,确保  Build Setting > Pakaging > Defines Module  设置为  Yes 。ui

 
用如下的语法将框架导入到不一样 target 的 Swift 文件里:
SWIFT
   
   
   
   
  1.   
  2. import FrameworkName 
 
用如下的语法将框架导入到不一样 target 的 Objc .m 文件里:
OBJECTIVE-C
   
   
   
   
  1.   
  2. @import FrameworkName; 
 
在Objective-C中使用 Swift

当你将 Swift 代码导入 Objc 文件以后,用普通的 Objc 语法使用 Swift 类。
OBJECTIVE-C
   
   
   
   
  1.   
  2. MySwiftClass *swiftObject = [[MySwiftClass alloc] init]; 
  3. [swiftObject swiftMethod]; 
 
Swift 的类或协议必须用  @objc attribute  来标记。以便在 Objc 中可訪问。

这个 attribute 告诉编译器这个 Swift 代码可以从 Objc 代码中訪问。假设你的 Swift 类是 Objc 类的子类,编译器会本身主动为你加入  @objc attribute 。

详见 Swift Type Compatibility。

 
你可以訪问 Swift 类或协议中用  @objc attribute  标记过东西,仅仅要它和 Objc 兼容。

不包含一下这些 Swift 独有的特性:

Generics - 范型 
Tuples - 元组 
Enumerations defined in Swift - Swift 中定义的枚举 
Structures defined in Swift - Swift 中定义的结构体 
Top-level functions defined in Swift - Swift Swift 中定义的顶层函数 
Global variables defined in Swift - Swift 中定义的全局变量 
Typealiases defined in Swift - Swift 中定义的类型别名 
Swift-style variadics 
Nested types - 嵌套类型 
Curried functions - 柯里化后的函数 
 
好比带有范型类型做为參数,或者返回元组的方法不能在Objective-C中使用。
 
为了不循环引用,不要将 Swift 代码导入到Objective-C头文件里。但是你可以在Objective-C头文件里前向声明( forward declare )一个 Swift 类来使用它。然而。注意不能在Objective-C中继承一个 Swift 类。

 
To reference a Swift class in an Objective-C header file
 
这样前向声明 Swift 类:
OBJECTIVE-C
   
   
   
   
  1. // MyObjcClass.h 
  2.   
  3. @class MySwiftClass; 
  4.   
  5. @interface MyObjcClass : NSObject 
  6. - (MySwiftClass *)returnSwiftObject; 
  7. /* ... */ 
  8. @end 
 
Product Module命名

Xcode 为 Swift 代码生成的头文件的名称。以及 Xcode 建立的 Objc 桥接头文件名,都是从你的 product 模块名生成的。默认你的 product 模块名和 product 名同样。然而,假设你的 product 名有特殊字符(nonalphanumeric,非数字、字母的字符)。好比点号,那么它们会被下划线( _ )替换以后做为你的 product 模块名。假设 product 名以数字开头,那么第一个数字会用下划线替换掉。
 
你可以给 product 模块名提供一个本身定义的名称,Xcode 会用这个名称来命名桥接的和本身主动生成的头文件。你仅仅需要在改动在  build setting  中的  Product Module Name  就能够。

 
故障建议和提醒

•把 Swift 和 Objc 文件看做一样的代码集合,并注意命名冲突;
 
•假设你用框架,确保  Build Setting > Pakaging > Defines Module  设置为  Yes 。
 
•假设你使用 Objc 桥接头文件。确保在  Build Settings  中 Objc 桥接头文件的  build setting  是基于 Swfit 编译器,即  Code Generation  含有头文件的路径。这个路径必须是头文件自身的路径,而不是它所在的文件夹。

 
•Xcode 使用你的 product 模块名。而不是 target 名来命名 Objc 桥接头文件和为 Swift 本身主动生成的头文件。详见 Naming Your Product Module;
 
•为了在 Objc 中可用, Swift 类必须是 Objc 类的子类,或者用  @objc  标记;
 
•当你将 Swift 导入到 Objc 中时,记住 Objc 不会将 Swift 独有的特性翻译成 Objc 相应的特性。详见列表 Using Swift from Objective-C;
 
•假设你在 Swift 代码中使用你本身的 Objc 类型,确保先将相应的 Objc 头文件导入到你的 Swift 代码中。而后才将 Swift 本身主动生成的头文件 import 到 Objc .m 源文件里来訪问 Swift 代码。
相关文章
相关标签/搜索