Swift和Objective-C是目前开发 Apple App的两门主要语言。Swift自2014年发布到目前为止其行业现状如何?Objective-C经过岁月的洗礼其稳定性、性能和开发特性支持度都是比较成熟的,Swift在这些方面是否已经比较完善,开发者是否可以开始着手大面积使用Swift进行项目开发?Swift和Objective-C在性能方面运行效率是否更好?具体分析请看下文展开。
Swift 于2010年7月启动开发,苹果WWDC2014开发者大会上正式发布问世,2015年12月正式开源(https://swift.org)
(1)谈起Swift,不得说说它的作者。
Swift的作者克里斯·拉特纳(Chris Lattner), 在05年之前,是美国UIUC大学的博士,在博士期间于2000年启动和开始主持LLVM项目,2005年7月加盟Apple Inc,之后整个LLVM研发团队全部加入Apple,致力于LLVM在Apple开发体系中的应用,目前LLVM已经被苹果IOS开发工具、Xilinx Vivado、Facebook、Google等各大公司采用。Apple也是LLVM项目的主要资助者。
Chris Lattner 加入Apple后,成为LLVM的主要负责人同时也是Xcode的主管,之后发起了Clang项目,于2010年7月启动开发Swift,之后14年发布Swift,15年开源Swift,于17年1月从Apple离职,随后这位在Apple工作了11年的技术大牛正式加入Tesla,6个月后从Tesla主动辞职。
Chris Lattner 作为一名70后程序员,发明了 LLVM、Clang、Swift,同时还是Xcode的Header,可以说是牛逼轰轰,大神中的大神,一个不可一世的人才。
(2)Swift的版本迭代历史
Swift 1.x版本属于刚开始阶段,2.x版本添加了很多新特性,3.x版本在Swift生涯中属于革命性的一步,其中改动了很多,语法和2.x版本也有较大差异。3.x到4.x版本主要是优化和保持稳定性,改动较小。文章后续内容主要针对Swift3版本。
(3)Swift的开发模式及目标
Swift设计的目标也是初衷是在程序运行角度要比C系语言(C, C++, and Objective-C)更快速,开发角度写法越简单越高效越好,让程序员在编程语言语法角度浪费的功夫越少越好,能把更多的时间和精力用于思考和开发应用程序逻辑。同时Swift原始设计为不仅可以用来开发Hello World这样的小程序,也可以用来开发一套完整的操作系统。Swift的出台至少奠定了Apple未来十年的发展方向,具有重大的战略意义。
Swift的官方说明:Safe、Fast、Expressive,更安全、更快速、更易表达。安全角度取消了Objective-C很多兼容的语法,只取其一,因为不再是C的超级,所以那些在C语言上存在的历史诟病,在Swift上不复存在。
Swift集成了很多高级语言的优秀特性,借鉴了很多高级语言的优秀语法,开发角度写法类似JavaScript等脚本语言,但是本身又属编译性质语言,是一门真正的编译语言,而非解释型。
Swift 结合了C和Objective-C 的优点并且不受 C 兼容性的限制。Swift采用安全的编程模式并添加了很多新特性,比如范型、闭包、函数式编程等,使编程更简单,更灵活,也更有趣。
开发模式方面,在开源之前主要依赖苹果Chris Lattner及所带领的开发团队,同时随着Swift的问世,Swift开发者社区也同步建立,Chris Lattner及所带领的开发团队非常关注社区建议和邮件列表,针对社区的建议,在Swift新特性支持上Swift团队并非单纯的建议的新特性就会加上,而往往是后退一步,思考更多,理解开发者真正需要的特性,此后考虑着手开发。
随着Swift的开源,开源社区开发力量的加入,开发者社区更加活跃,Swift也在更加趋于完善。
(1)编程语言排行榜
看近三年三月份的编程语言排名数据,Swift由2015年的23名上升至2016年的14名,在2017年上升至第10名;再看看Objective-C,由2015年的第3名下降至2016年的第15名,在今年下降至16名。Swift编程语言日趋上升。
(2)开发社区生态
正如Chris Lattner在离开Apple前的近几年已不怎么过问LLVM自身的事,而主要投入精力到Swift的研发上一样,LLVM彼时已建立起成熟的开发者社区,彼时的LLVM已是社区的LLVM,Chris Lattner在将主要精力转向Swift的研发上时,LLVM项目自身的存活与否已经不会有什么影响。
Swift也一样,Chris Lattner离开Apple前,也已经建立起成熟的Swift开发者社区,此时的Swift也不再只是Apple的Swift,此时的Swift已是社区的Swift,Chris Lattner的离开并不会对Swift的发展造成大的影响。加上开源的力量,相信Swift会继续勇往前行。
(3)开源库占比
目前GitHub(https://github.com)上Swift语言的开源项日大约是Objective-C语言的开源项目的5倍还多。
(4)本身成熟度、库成熟度、Xcode集成环境支持程度
Swift经过3.x版本的改进,语法和性能上已开始趋于稳定,后期4.0版本主要是优化提高性能和稳定性,改动不多,本身成熟度已开始趋于完善。
库的成熟度,经过Apple的努力,相信也有不少提升,很多在2.x版本还没有Swift版本的库,3.x版本到4.x版本已经有很多库用Swift进行了改写。库的性能和稳定性目前还不好说,还需要经过海量App的线上验证,需要经过一段时间的洗礼才能得出结论。既然Apple已经转向Swift,相信即使有些大大小小的问题苹果也会积极处理和解决。这方面不用太过担心。
Xcode 8就开始支持Swift,目前Xcode 9已经同时支持Swift 3.2和Swift 4.0 版本,可在工程设置里面设定。
和OC简单语法对比:
1.简单值定义
Swift取消了Mutable和非Mutable的区分,所有的简单值定义改为:通过let定义常量,通过var定义变量。不再有宏定义,在Swift里面要实现宏定义,直接用let定义全局常量。如下:
let和var定义简单值如果指定初始值则不再需要指定类型,不指定初始值则需要明确指定类型。初始化时指定初始值时编译器会自动推断变量类型。
参数打印不再需要通过%加固定字符来指定打印格式,直接\反斜杠一对圆括号里面包含常量、变量、字面量和表达式即可。
数组成员和字典Value可以直接是float、int等基础类型,不用再像oc里面需要转成NSNumber对象。
(1)使用 if 和 let 来处理值缺失的情况。一个可选的值是一个具体的值或者是 nil 以表示值缺失。在类型后面加一个问号来标记这个变量的值是可选的。
如果optionalName变量的可选值是 nil,条件会判断为 false,大括号中的代码会被跳过。如果不是 ,会将值解包并赋给 let后面的name常量,这样代码块中就可以使用这个值了。
(2)另一种处理可选值的方法是通过使用 ?? 操作符来提供一个默认值。如果可选值缺失的话,可以使用默认值来代替。一个??即搞定,不再需要像oc里面需要写if判断或是问号表达式,Swift变得更加简洁。
在C/Objective-C中,if、while、for之后的判断式并不需要一定传入布尔类型。也可以传入整型、指针等类型,只要非0就为真,并且赋值是有副作用的。比如:
上面的代码返回a的数值,这样就有可能出现将判断:
错写成:
为避免这个问题,有种变通写法:
这种写法被称为Yoda表达式,因为《星球大战》中的Yoda大师喜欢使用这样奇特的倒装句子。
Swift强制要求if、while、for后面判断式子一定需要传入布尔类型。因此写成以下这种判断就会编译错误,因为a = 0的结果是a是Int型而非布尔型。Yoda表达式这种变通写法再也没有必要。
Swift里面的Bool常量值是true和false。
Swift中的实现:
switch中一个case语句执行完成后就不再向下执行。Case里面没有break语句,不会再偶然地出现bug!
8.区间运算符
(1)闭区间运算符
闭区间运算符(a…b)定义一个包含从a到b(包括a和b)的所有值的区间。a的值不能超过b。在for-in循环中非常有用。
(2)半开区间运算符
半开区间运算符(a..<b)
定义一个从a到b但不包含b的区间。之所以称为半开区间,是因为该区间包含第一个值而不包括最后的值。
9.强制使用大括号
在C/Objective-C中,if、while、for之后的语句假如只有一行,是可以省略掉大括号的 。比如:
当后面的人修改代码,或多人修改同一代码再合并时,可能会在if后面直接插入一行,这样就一定会return了。
Swift里面必须要有大括号。
Swift里面guard语句简化了函数实现里面参数有效性的check。像if语句一样,guard语句的执行取决于一个表达式的布尔值。
可以使用 guard 语句来要求条件必须为真时,以执行guard语句后的代码。不同于 if 语句,一个 guard 语句总是有一个 else 从句,如果条件不为真则执行 else 从句中的代码。
Swift 中的 Array 类型还提供一个可以创建特定大小并且所有数据都被默认的构造方法。
Swift中的元组(tuples)把多个值组合成一个复合值。元组内的值可以是任意类型,并不要求是相同类型。Eg:
元组的最大用途在函数可以返回多个值:
Swift里面定义一个闭包,闭包 = {(形参) -> 返回值 in 代码实现},in 用于区分函数定义和代码实现:
最简单的闭包,如果没有参数/返回值,则参数/返回值/in 统统都可以省略
范型的应用场景:
swapTwoInts(::)、swapTwoStrings(::) 和 swapTwoDoubles(::) 的函数功能都是相同的,唯一不同之处就在于传入的变量类型不同,分别是 Int 、 String 和 Double 。
在实际应用中,通常需要一个更实用更灵活的函数来交换两个任意类型的值,Swift里面通过范型来解决。如下:
Swift里面字符串可以直接拼接:
也可以直接比较:
Swift的语法设计使一些C/Objective-C常见错误不可能再出现,比如:字符串插值参数打印;if、while、for之后的判断式强制是Bool类型;switch中case语句取消break;if、while、for之后的语句强制使用大括号。
同时更多的是让语法更简单,编程语言的语法进行简洁化和优化,让程序员省掉关注语法的时间,将更多的时间和精力放在应用程序逻辑开发上。比如:省略分号;??可选值;switch中可以直接对String类型进行判断;区间运算符;guard语句;Array初始化中的repeating;元组;闭包;范型;字符串拼接和直接比较。
以下从开发中常用的基础语句运行效率方面进行对比,对比Swift(3.2和4.0两个版本)和Objective-C两者的性能差异。
a. 对比维度:循环、自增(Swift 3.0以前有自增运算,3.0后取消了)、赋值、添加字符串到数组、添加整数到数组、添加字符串到字典、添加整数到字典、拼接字符串。
b. 每项操作运行10w次的耗时对比。
c. 模拟器:iPhone 6, iOS 10.2; 真机:iPhone 6, iOS 10.3.3
d. Debug模式下优化级别设为None:
代码:见附件
(1)模拟器对比结果:
Swift 3.2:
Swift 4.0
Objective-C:
(2)真机对比结果:
Swift 3.2:
Swift 4.0
Objective-C:
在设定的几项对比维度内: a. Swift 3.2到Swift 4.0,性能运行效率提升不明显,基本没有提升; b. 循环、自增、赋值、字符串数组处理、value为字符串或数值的字典处理操作,Swift性能不如Objective-C; c. 整型数组处理,Swift优于Objective-C; d. 字符串拼接处理,Swift性能较Objective-C优势明显。
整体来看,Swift和Objective-C相比,除了字符串处理优势明显外,其它基础操作方面性能稍逊色。
Swift是一门静态编译语言,Objective-C是一门运行时动态绑定语言,因为Objective-C的动态特性,导致编译器能做的优化工作是很有限的,很多工作只能放到运行时处理,所以从这方面看Swift在编译时能做的优化能做的更多,从而性能提升空间也较OC的大,但目前来看Swift只有字符串处理方面优化的比较不错,其它方面并不明显。
Swift和Objective-C互调需要新建一个XXX-Bridging-Header.h文件做桥接,具体请参看稍后将会发的另外一篇文章(后续)
Swift版本更新频繁,比如2.x到3.x去掉了”++”、”--”自增自减运算。2.x时网上有很多同行验证Swift的自增自减运算相对OC有严重的性能问题,2.x到3.x去掉了不知是不是当前尚未解决此问题或是有其它的替代方案。
3.x到4.x一个典型的改动点是关于set selector,在Swift 3.x时,selector函数定义前不需要添加@objc修饰。Swift 4.0中则必须要加@objc修饰。其它的改动这里不再详述,请参阅苹果官方文档。
Swift所面临的问题,也即到目前为止大多数程序员吐槽和诟病的关于动态特性(或叫“反射特性”,类似Java中的反射)。
Objective-C是一门动态语言,对开发者来说即运行时编程,可以在runtime进行类和方法的增删修改,甚至是对无源码的class和类库进行method swizzling改变原有库接口的功能等,给开发者提供了足够大的权限和便利,因为权力够大,因而容易过度使用,然而也正是这种动态特性的过度使用,导致OC这门语言是不安全的。
Swift并非在C或OC基础上进行开发,而是重新设计和布局,Swift的目标在于具备处理广泛问题的能力,包括服务器端开发和系统编程。因为要求更高的安全性,而动态特性本身容易导致过度使用,动态特性本身是一把双刃剑,所以苹果开发工程师整个Swift团队也正在思考一种更合理的解决方案。
依据前面“四”的对比,Swift和Objective-C相比在字符串处理方面优势明显,其它方面和OC差不多,实际项目中可以根据项目性质合理选择两者之一做为开发语言,甚至不同情境下应用各自语言的各自的优势,不同模块采用不同的语言做开发。
Swift融合了至目前为止大多数高级语言的优秀特性,可谓是站在所有语言的肩膀上,汲取所有语言的精华,是目前行业内最优秀的语言,期待未来在稳定性、性能上的改善能取得更多质的突破。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。