您的位置:首页 > 移动开发 > Objective-C

在同一个项目中使用Swift 和 Objective-C

2014-06-05 11:12 197 查看
拷贝来自原创地址

原创翻译,转载注明

原文链接:原文

Swift 对Objective-C 的兼容性允许你创建一个包含这两种语言文件的工程。你可以使用名为:“mix and match”的特性来编写包含混合语言代码的app。使用”mix and match”,你可以使用swift的新特性来编写app一部分的功能,同时无缝的和现有的Objective-C(下文简称OC) 代码相融合。


Mix and Match 概述

OC和swift代码可以在一个工程中共存,无论这个工程原本是OC还是swift工程。你可以轻易的在已有工程文件中添加另一种语言文件。对于创建混合语言的app或framework 来说,这种自然的工作方式和使用单种语言一样直截了当。

写混合语言的流程取决于你是写app还是framework,情况略微不同。对于同一个target要想用两种语言混写,大体的工作流程如下图所绘,具体的内容会在后面的章节描述。




在同一个app Target里进行语言代码导入

如果你在写一个混合语言的app,你应该需要在OC中访问swift代码或者从swift中访问OC代码。这个流程会在本章节描述,但仅仅适用于非framework的targets。


把OC代码导入为Swift可用

要在同一个target中导入一些OC文件能为Swift所用,你要依靠”Objective-C bridging header”这个特性来保证OC文件对swift来说是可见的.当你在一个OC项目中添加一个swift文件或者在swift项目中添加OC文件,Xcode会创建头文件来保证两者的可互访性。



当点击同意的时候,xcode会在你创建OC文件时同时创建一个头文件,它是根据你工程的product module name加上”-Bridging-Header.h” 拼接而成的。关于product module name的更多信息,后面章节会提到。


在同一个 app target中把OC代码导入为Swift

1.在你的Objective-C bridging header文件中,把所有你想暴露给swift 的头文件写在里面,例如:

1
2
3
4
5

OBJECTIVE-C

#import "XYZCustomCell.h"
#import "XYZCustomView.h"
#import "XYZCustomViewController.h"

2.在Build Settings里,确保项目Swift Compiler – Code Generation中 Objective-C Bridging Header指向了你的Bridging Header文件,这个path指向的是你的Bridging Header文件,而不是它所在的目录

这个path应该是相对路径,和Build Settings定义的 Info.plist一样。大部分情况下你不需要修改这个配置

任何一个在 bridging header 文件中列出来的OC头文件对swift来说都是可见的。在这个target里 OC代码的功能对任何一个swift文件都是自动可用的,不需要导入任何声明。你可以像使用系统classes一样来使用你自定义的OC代码了。

1
2
3
4
5

SWIFT

let myCell = XYZCustomCell()
myCell.subtitle = "A custom cell"


把Swift代码导入为OC可用

当你想让Swift代码导入为OC可用时,你要依赖Xcode-generated header 这个文件去向OC暴露接口。这个自动生成的文件是一个OC的头文件,其中声明了项目中所有Swift代码的接口。它可以理解为Swift代码的伞头(umbrella header)。这个文件的命名是以你的product module name加上”-Swift.h” 拼接而成的,关于product module name的更多信息,后面章节会提到。

你不需要做任何额外事情来创建这个文件,你只需要在你们的OC代码中import,然后使用就好了。注意,swift代码中使用的所有OC代码也会被generated header中的Swift接口所引用。如果你在SWift代码中使用le 自己的OC代码(译者注:非系统class),那么你必须在OC的.m文件中先导入swift代码中引入OC的OC头文件,然后才可以导入Swift generated header来访问swift代码。(译者注:简单的就是说在Objective-C bridging header中声明的头文件让你可以在swift中访问OC代码,当你在OC中访问swift代码时候,必须在导入generated
header之前先导入这些OC头文件。基于这点,要想在预编译pch文件中导入generated header是不现实的,貌似Xcode6以后pch已经被干掉了)


在同一个app target中将Swift代码导入为OC可用

在同一个target中,将以合适名称命名的Swift代码接口文件(generated header)导入到任何需要用到swift代码的OC.m文件中

1
2
3

OBJECTIVE-C

#import “ProductModuleName-Swift.h”

在任何导入这个声明头文件的地方,Swift代码都是可见的。




在同一个Framework target里进行语言代码导入

如果你在写一个混合语言的framework,你应该需要在OC中访问swift代码或者从swift中访问OC代码。


把OC代码导入为Swift可用

要在同一个 framework target中导入一些OC文件能为Swift所用,你需要在 Objective-C umbrella header中导入这些OC的头文件


在同一个 framework target中把OC代码导入为Swift 可用

1.在Build Settings-Packaging中,确保 Defines Module setting被设置为YES 2.在你的umbrella header file中,和app target一样,导入你想要暴露给swift的头文件。例如:

1
2
3
4
5

OBJECTIVE-C

#import "XYZCustomCell.h"
#import "XYZCustomView.h"
#import "XYZCustomViewController.h"

任何一个在 umbrella header 文件中列出来的OC头文件对swift来说都是可见的。在这个target里 OC代码的功能对任何一个swift文件都是自动可用的,不需要导入任何声明。你可以像是使用系统classes一样来使用你自定义的OC代码了。

1
2
34

SWIFT

let myCell = XYZCustomCell()
myCell.subtitle = "A custom cell"


把swift代码导入为OC可用

当你要想让Swift代码导入为OC可用,你不需要在 umbrella header 中导入任何东西。和app target类似,你只需要在需要用到swift代码的OC .m文件中导入 Xcode-generated header 文件就好了


在同一个 framework target中把swift代码导入为OC可用

1.在Build Settings-Packaging中,确保 Defines Module setting被设置为YES 2.在同一个target中,将以合适名称命名的Swift代码接口文件(generated header)导入到任何需要用到的OC .m文件中

1
2
3

OBJECTIVE-C

#import “ProductModuleName-Swift.h”

在任何导入这个声明头文件的地方,Swift代码都是可见的。




导入外部Frameworks

你可以导入完全使用OC、swift或者混合代码编写的外部frameworks。使用这些frameworks的方法是一样的,无论其是单一语言编写还是混合编写的。当你导入一个外部framework,请确保你的项目Defines Module build setting被设置为Yes。

你可以在不同target中导入一个framework到swift文件中:

1
2
3

SWIFT

import FrameworkName

你可以在不同target中导入一个framework到OC的.m文件中:

1
2
3

OBJECTIVE-C

@import FrameworkName




在OC中使用Swift

当你导入swift代码到OC中时候,使用OC的常规语法就可以调用swift的classes了

1
2
34

OBJECTIVE-C

MySwiftClass *swiftObject = [[MySwiftClass alloc] init];
[swiftObject swiftMethod];

一个Swift class 或者 protocol 必须使用@objc的属性标记才可以被OC使用。这个属性告诉编译器这段swift代码可以被OC所访问到。如果你的swift class 是由 Objective-C class 派生的,那么编译器会自动帮你加上@objc标识,获取更多信息请访问:Swift
Type Compatibility

当一个class或者protocol 被有@objc 属性标识的时候,你可以访问这个class或者protocol 里面所有的东西,因为它跟OC是兼容的。这里有一些不兼容的特性列表(Swift-only):

Generics
Tuples
Enumerations defined in Swift
Structures defined in Swift
Top-level functions defined in Swift
Global variables defined in Swift
Typealiases defined in Swift
Swift-style variadics
Nested types
Curried functions

比如,一个方法有一个generic类型的参数或者返回值是个tuple类型,那它是不能被OC所用的

为了避免循环引用,不要在一个OC的头文件中导入swift。相反,你可以直接在OC的头文件中声明和使用swift class。然而要注意你不能在OC去子类化swift.


在OC的头文件中引用一个Swift class

直接声明和使用

1
2
3
4
56
7
8

OBJECTIVE-C

@class MySwiftClass;

@interface MyObjcClass : NSObject
- (MySwiftClass *)returnSwiftObject;
/* ... */
@end


给 Product Module 命名

Xcode-generated header和 Objective-C bridging header 的命名都是由product module name得来的。默认情况下 product module name和product name是一样的。然而如果你的 product name包含非字母数字字符,例如点(.),他们会被下划线(_)取代。如果你的product name是以数字开头,那么首字符的数据也会被下划线取代。

你同样可以自定义你的product module name。Xcode会使用你改过的name来命名 bridging 和 generated headers。你可以在build setting里面进行修改。


问题建议和提醒

将你的Swift和OC文件放在同一个集合里,当心命名冲突
如果你开发frameworks,确保Packaging中的Defines Module被设置为YES
如果你使用到Objective-C bridging header,确保,确保项目Swift Compiler – Code Generation中 Objective-C Bridging Header指向了你的Bridging Header文件,这个path指向的是你的Bridging Header文件,而不是它的目录
Xcode使用 product module name而不是 target name来命名bridging header and the generated header.更多信息参考上文”给 Product Module 命名”章节。
一个 swift class 必须由OC class派生或者被@objc标识 才能被OC所获取和使用
当你在OC中使用Swift,记住OC并不能读懂swift的一些特性,参考上文中的列表
如果你在SWift代码中使用自己的OC代码,那么你必须在OC的.m文件中先导入swift代码中引入OC的OC头文件,然后才可以导入Swift
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: