说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

Swift与Objective-C的兼容“黑魔法”:@objc和Dynamic

HTML文档下载 WORD文档下载 PDF文档下载
Cocoa框架早已烙上了不可磨灭的OC印记,而无数的第三方库都是用OC写成的,这些积累无论是谁都不能小觑。苹果采取了允许开发者在同一个项目中同时使用Swift和OC进行开发的做法,但要想实现互通,又需添加哪些桥梁?

虽然说Swift语言的初衷是希望能摆脱Objective-C的沉重的历史包袱和约束,但是不可否认的是经过了二十多年的洗礼,Cocoa框架早就烙上了不可磨灭的Objective-C的印记。无数的第三方库是用Objective-C写成的,这些积累无论是谁都不能小觑。因此,在最初的版本中,Swift不得不考虑与Objective-C的兼容。


Apple采取的做法是允许我们在同一个项目中同时使用Swift和Objective-C来进行开发。其实一个项目中的Objective-C文件和Swift文件是处于两个不同世界中的,为了让它们能相互联通,我们需要添加一些桥梁。

首先通过添加{product-module-name}-Bridging-Header.h文件,并在其中填写想要使用的头文件名称,我们就可以很容易地在Swift中使用Objective-C代码了。Xcode为了简化这个设定,甚至在Swift项目中第一次导入Objective-C文件时会主动弹框进行询问是否要自动创建这个文件,可以说是非常方便。

但是如果想要在Objective-C中使用Swift的类型的时候,事情就复杂一些。如果是来自外部的框架,那么这个框架与Objective-C项目肯定不是处在同一个target中的,我们需要对外部的Swift module进行导入。这个其实和使用Objective-C的原来的Framework是一样的,对于一个项目来说,外界框架是由Swift写的还是Objective-C写的,两者并没有太大区别。我们通过使用2013年新引入的@import来引入module:

@import MySwiftKit;

之后就可以正常使用这个Swift写的框架了。

如果想要在Objective-C里使用的是同一个项目中的Swift的源文件的话,可以直接导入自动生成的头文件{product-module-name}-Swift.h来完成。比如项目的target叫做MyApp的话,我们就需要在Objective-C文件中写:

#import "MyApp-Swift.h"

但这只是故事的开始。Objective-C和Swift在底层使用的是两套完全不同的机制,Cocoa中的Objective-C对象是基于运行时的,它从骨子里遵循了KVC(Key-Value Coding,通过类似字典的方式存储对象信息)以及动态派发(Dynamic Dispatch,在运行调用时再决定实际调用的具体实现)。而Swift为了追求性能,如果没有特殊需要的话,是不会在运行时再来决定这些的。也就是说,Swift类型的成员或者方法在编译时就已经决定,而运行时便不再需要经过一次查找,而可以直接使用。

显而易见,这带来的问题是如果我们要使用Objective-C的代码或者特性来调用纯Swift的类型时候,我们会因为找不到所需要的这些运行时信息,而导致失败。解决起来也很简单,在Swift类型文件中,我们可以将需要暴露给Objective-C使用的任何地方(包括类,属性和方法等)的声明前面加上@objc修饰符。注意这个步骤只需要对那些不是继承自NSObject的类型进行,如果你用Swift写的class是继承自NSObject的话,Swift会默认自动为所有的非private的类和成员加上@objc。这就是说,对一个NSObject的子类,你只需要导入相应的头文件就可以在Objective-C里使用这个类了。

@objc修饰符的另一个作用是为Objective-C侧重新声明方法或者变量的名字。虽然绝大部分时候自动转换的方法名已经足够好用(比如会将Swift中类似init(name: String) 的方法转换成-initWithName:(NSString *)name这样),但是有时候我们还是期望Objective-C里使用和Swift中不一样的方法名或者类的名字,比如Swift里这样的一个类:

class 我的类 {    func 打招呼(名字: String) {        println("哈喽,\(名字)")    }}我的类().打招呼("小明")

Objective-C的话是无法使用中文来进行调用的,因此我们必须使用@objc将其转为ASCII才能在Objective-C里访问:

@objc(MyClass)class 我的类 {    @objc(greeting:)    func 打招呼(名字: String) {        println("哈喽,\(名字)")    }}

这样,我们在Objective-C里就能调用 [[MyClass new] greeting:@"XiaoMing"] 这样的代码了(虽然比起原来一点都不好玩了)。另外,正如上面所说的以及在Selector一节中所提到的,即使是NSObject的子类,Swift也不会在被标记为private的方法或成员上自动加@objc。如果我们需要使用这些内容的动态特性的话,我们需要手动给它们加上@objc修饰。

添加@objc修饰符并不意味着这个方法或者属性会变成动态派发,Swift依然可能会将其优化为静态调用。如果你需要和Objective-C里动态调用时相同的运行时特性的话,你需要使用的修饰符是dynamic。一般情况下在做App开发时应该用不上,但是在施展一些像动态替换方法或者运行时再决定实现这样的 "黑魔法" 的时候,我们就需要用到dynamic修饰符了。在之后的KVO一节中,我们还会提到一个关于使用dynamic的实例。

作者:王巍(@onevcat),iOS和Unity3D开发者。

本文转载自:Swifter

点击链接进入Swift技术社区,了解更多Swift开发的技术热点内容!


CSDN JOB移动工程师专场招聘,直击20家企业高薪职位-->http://job.csdn.net/event/mobdev.html

周末巨献:100+诡异的数据集,20万Eclipse Bug、死囚遗言等 TIOBE 2014年6月编程语言排行榜:Swift能否取代Objective-C? 移动游戏后端:开发还是购买?你必须知道的6件事 Vuforia SDK 3.0发布在即 全球注册开发者已逾10万 最受职场青睐的十大热门云计算技能盘点 Android Bootstrap:开发也能用模板,省时又省力! Facebook开源又一力作,欲借Broadcom开放交换机 华为敏捷网络:坚持被集成,引领ICT融合 专访赵桂华:.Net也有春天及高性能网站架构实践 《近匠》Testin:云测试除了APP和真机 还有可穿戴和汽车 应用开发利器FXForms:iOS上实现各种Form View Firefox 30正式版:支持GStreamer 1.0技术、内置全新Gecko 30内核 从阿里、UC联姻 看移动互联网“入口”之争 AppCode发布3.0.1更新,支持Xcode 6和Swift 智能家居持续升温:苹果HomeKit合作伙伴Honeywell发布恒温器 欲与谷歌、亚马逊抗衡,苹果推CloudKit拥抱云服务 针对新一代物联网应用 Atmel推全新32位微控制器 实时计算,流数据处理系统简介与简单分析 Cue:秒杀HealthKit,打造自己的家庭医生 新iPhone要来:4.7就够了么?我们还有更大的 Docker迈入云(DockerHub)+端(Docker引擎)时代 《近匠》壹枱智能钢琴:改造音乐行业的新“玩”家 圣何塞Hadoop Summit 2014看点 唯快不破!90后大学生9天完成近670页的Swift语言文档翻译 一周消息树:Java、.NET、Web技术应用特点 苹果生态格局:软硬件之后,iLifestyle才是王道 小米互娱总经理尚进:独立游戏当为发烧而生 哪些编程语言、框架/平台最受企业青睐? 高德LBS应用大赛:百万大奖、千万基金等你来拿! Gartner:有数据有真相 从浪潮看服务器市场走势 PhoneGap 3.5.0发布,不再支持iOS 5和ARM64 网页问题 再次跪求教物资进库表和物资库存表的问题! 请问高手,如何在asp中调用,在线等候… 关于局域网的一个问题 一个表的记录写到另一个表中的问题??UP有分 蔡鸟求助:如何用vc++把一个文件(比如图纸)存到局域网中别的机器上 我有IIS的服务器的网站,我用什么软件能知道有谁正在下载什么文件?? 求MICROSOFT VISUAL STUDIO.NET 2002 中文企业版,2003不要,谢谢~ MySQL JDBC 驱动程序在哪里下载? 请教八数码难题的解法! 有在ASP 下 用过regexp类的吗?? 急救!关于ON_WM_ACTIVEAPP的问题 MySQL JDBC 驱动程序在哪里下载? mysql for linux 启动问题? 51job的动态简历预览功能暴快,有谁知道采用了什么样的技术? 请教为什么KeyUp事件不响应? 程序有两个线程时,如果子线程是个死循环,永远不停(如监听一个Socket),那当我的主线程return了后,程序会不会退出呢? 我重载了WM_NCPAINT来画窗体边框和标题栏,可是菜单就不见了,如何给画出来? 如何将INTERBASE中的数据导出到EXCEL文件中?! 关于C# 需要server2003企业中文版(激活的)地址! sql查询问题 update 的问题 急!IIS连接不上 装上JDataConnection Server之后,在数据源ODBC中的驱动程序列表中没有JDBC驱动算不算问题,高分求解! 短消息服务提供商(SP)程序问题 activeX控件问题,急盼高手帮助! 请教八数码难题的解法! 如果一个dll,在它里面有一个窗口,而有一个函数是这个窗体类的一个函数,那么如果在使用这个dll文件中的这个函数。 谁能给一个测试是否是EMAIL的函数?急! 如何实现关键字查询? 只能让家里的电视出现更多的台,比如解码器什么的! 急问:那位了解 sys/wait.h ,它的功能是什么? 求MICROSOFT VISUAL STUDIO.NET 2002 中文企业版,2003不要,谢谢~ saucer(思归)在吗?有问题请教! 哪里有C++ Builder 下载的。 TTrayIcon中的图标颜色只能显示16色的吗? HELP!!!XML怎么写成物理文件到本地? 这是为什么呀?电脑高手请进。。。 也说技术人员创业 高分:虚拟主机问题 快被OVERLAY搞死了,急救 中了“盗贼”木马,如何删除? 请网络高手来看看这个问题,给我点提示和建议?急急急 汉字在exe 文件的十六进制 能否 转换得来? 气死人了,在jbuilder8中被logic:iterate搞死了,累,急救 pb数据窗UPDATE的怪问题!很怪!!! 配置问题求救! 请问Access中可以用select case ........when else end的函数吗? 一定要把AutoPostBack设定成true才能响应事件? 但是那样动态生成的控件又都没了…… 急 哪位知道哪有OpenGL高级编程的培训 恭贺新春 xsh 请问英语单选怎么选,为什么?多谢!It makes good ____ to bring an umbrella; it seems to be raining today.A. sense B. reason C. suggestion D. advice 坚强的人是如何克服困难的有什么困难 如何克服的 占鸿渐,采凤飞的意思占鸿渐就是占卜得到“渐”卦了,那么采凤飞呢? 求激励 人克服困难 坚强的 歌曲 指人克服困难后、收获了别样的精彩的古诗文、 1. “欲加之罪,何患无辞”这个典故出自哪个时期? 苹果和葡萄你会喜欢什么 清晰了解自己的不足和弱点,却发现很难改变,因为自己不知道怎么改变?清晰了解自己的不足和弱点,却发现很难改变,因为自己不知道怎么改变,别人给自己说了,却也难以去做,想知道自己这是 恭贺春节的话语有那些 你有没有 新视野大学英语听说2 第五六单元 quiz答案 外媒:以色列将在东耶路撒冷建1500美13岁男生携玩具枪被警察射杀 FB美国“追梦者”空天飞机在测试中滑出跑“窃听门”在哪里刺伤了美欧关系?中国和塞浦路斯签协定保护文化财产宠物犬被指与主人长得像 日学者称关键JAEA报告称福岛核电站附近森林核辐法国拟试行按剂量出售抗生素以减少药物沙特女性抗议者拟无视政府禁驾令“顶风美称监听欧洲公民的是欧情报机构 美只美科学家称“亚洲鲤鱼”大量繁殖威胁当40多辆车一夜被划伤,他干的?占道停车把救护车堵在小区门外 业主说蓝狮提前三轮夺得英超桂冠婴儿奶粉配方注册有助改变市场乱象这个80后重庆小伙 成为英国终身讲席卫计委:“兰菌净”并非疫苗重庆出版集团八月出版 《日本远东战争攒劲四万分 iPhone6被他们拿回“三桶油”同日宣布换帅5月中旬计划停电612路公交上扔钱包的女士 警察在找腾龙图奇门相师武极天下异界强兵大明火枪兵超级外星基地超级血牛网游之王者召唤仙遁将骨末世之后三百年珠江南田温泉旅游万绿园旅游深圳湾公园旅游塔敏查干沙漠旅游御碑亭旅游梦幻谷旅游佤山旅游广允缅寺旅游小金旅游仰天山旅游偶园旅游
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘