深度编程

Swift与Objective-C混和编程

2015-11-29  本文已影响1984人  kimimaro

14年6月3日苹果发布Swift以来,这门语言以让人惊讶的速度在成长,越来越多的开发者关注学习,很多App和开源库也在从Objective-C迁移到Swift上。

Swift语法确实更新进、更漂亮,而在实际开发过程中,由于Objective-C更贴近底层,可以使用如OC Runtime这样的黑魔法,很多开源库也是依赖其实现。因此OC和Swift混编应该一个长期的趋势,之前只是依赖于Xcode自动引入bridge header等类似的机制,没有仔细去理解,借着新做项目用到evernote oc库的机会好好的总结一下。苹果提供的Swift与Objective-C混编方案都是基于Xcode和LLVM编译,采用Mix and Match机制。


从开发者实现角度根据不同的混编场景可以分为如下几种情况:

普通代码文件混编方案:

Swift引用OC实现通过桥接头文件,OC引用Swift实现直接importProductModuleName-Swift.h这个文件即可。

OC引用Swift实现

ProductModuleNameBuild Settings里面配置:

默认用ProductName,可以支持自定义。(注明:Framework项目不支持自定义)

Swift引用OC实现

Swift引用OC实现稍微麻烦一点,需要自己生成一个bridge header文件,和创建普通.h方式相同File > New > File > (iOS, watchOS, tvOS, or OS X) > Source > Header File,名字随意,然后配置到Build Settings - Swift Compiler - Code Generation下的Objective-C Bridging Header选项。

注意路径从项目根目录开始计算,可以使用..来指定与根目录平级目录。bridge header内import所有想要在swift中使用的OC类,就会作为一个module在swift中使用。例如:

#import "XYZCustomCell.h"    

#import "XYZCustomView.h"   

#import "XYZCustomViewController.h"

Swift中用如下代码访问:

let myOtherCell = XYZCustomCell()    

myOtherCell.subtitle = "Another custom cell"

FYI. 语言类型为Swift的项目引入OC文件时Xcode会给个创建bridge header的提示,自己会配置了之后用处不大:

Framework项目中使用代码混编方案:

Umbrella Header的相关知识苹果没有给出很明确的说明,只有以前介绍Umbrella Framework的时候介绍过,找了很久发现iOS - Umbrella Header在framework中的应用这篇文章介绍的很好,详细的内容可以进入了解。

Swift引用OC实现

现在我们只需要了解Framework里面Swift引用OC逻辑需要一个与ProductName同名的.h文件作为Umbrella Header,如果不存在则创建一个。不需要在Build Settings配置因为这文件是map modules的时候自动指定的,如果基于某种原因(比如这个同名文件已经被用来写其他逻辑)一定要自定义的话可以参考上面文章里介绍的方法。第二步到Build Settings - Packaging中将Defines Module选项设为YES。然后将Swift中需要引用的OC逻辑引用进来,访问方式同普通代码混编

#import "XYZCustomCell.h"    

#import "XYZCustomView.h"    

#import "XYZCustomViewController.h"

OC引用Swift

实现OC引用Swift同样需要将Defines Module选项设为YES,其余和普通代码混编相比只是改了个引用文件的方式:#import

引用外部Framework时混编

方案:

重要前提

这里有一个重要的前提是这个外部Framework在编译时必须开启了Defines Module,如果没有开启并且没有Framework源码的情况下还是绕路吧。

external framework混编

在这种情况下当前App使用外部Framework是不关心其内部到底是Swift实现、OC实现还是本身就是混编实现的。只需要Swift使用Framework逻辑时添加import FrameworkName,OC使用时在任意.m文件中添加@import FrameworkName;语法即可。

混编后哪些逻辑可以被另一种语言引用到?

Swift中可以被OC引用的逻辑:

OC中由于开发习惯的原因基本上头文件中的属性、方法都可以被swift访问到。

Evenote-Mac Framework混编时遇到的问题

  1. Evenote-Mac这个奇葩的Framework名字在生成umbrella header的时候报错:

warning: EvernoteSDK-Mac is not a valid PRODUCT_NAME for use with framework targets enabling DEFINES_MODULE (name is not a valid C99 extended identifier)

warning: no umbrella header found for target 'EvernoteSDK-Mac', module map will not be generated

因为名字中有-字符,所以只能替换或者去掉;

  1. 改名时建议直接改target的名字,只改module的名字就会报错:

Warning: PRODUCT_MODULE_NAME may not be overridden for framework target 'EvernoteSDKMac'

参考链接

  1. Mixed language framework

  2. 链接1回答中还有个Demo

  3. 官方对Umbrella Framework的一点介绍

  4. 对Umbrella Framework的一篇更好的介绍

  5. so上有关framework name的回答

上一篇 下一篇

猜你喜欢

热点阅读