编程语言之Swift
2023-04-07 09:40:47 阿炯

Swift苹果公司推出的支持多编程范式和编译式的编程语言,用来编写基于macOS/OS X、iOS、iPadOS、watchOS和tvOS的软件。于2014年在苹果开发者年会(WWDC)发布了Swift编程语言,从设计上看苹果公司让Swift与Objective-C共存于其公司的操作系统上。2.2及以后版本采用ApacheV2许可证授权。


2010年7月,苹果开发者工具部门总监克里斯·拉特纳开始着手 Swift 编程语言的设计工作,以一年时间完成基本架构后,他领导了一个设计团队参与其中。Swift大约历经4年的开发期,2014年6月对外发表。2015年6月8日,苹果于WWDC2015上宣布,Swift将开放源代码,包括编译器和标准库。同年12月3日,苹果宣布开源Swift,并支持Linux,苹果在新网站swift.org和托管网站Github上开源了Swift,但苹果的App Store并不支持开源的Swift,只支持苹果官方的Swift版本,官方版本会在新网站swift.org上定期与开源版本同步。长达 600 多页的《The Swift Programming Language 》可以在线免费下载。

苹果宣称Swift的特点是:快速、现代、安全、互动,而且明显优于Objective-C语言。Swift以LLVM编译,可以使用现有的Cocoa和Cocoa Touch框架。Xcode Playgrounds功能是Swift为苹果开发工具带来的最大创新,该功能提供强大的互动效果,能让Swift源代码在撰写过程中能即时显示出其执行结果。拉特纳本人强调,Playgrounds很大程度是受到布雷特·维克多理念的启发。


Swift取消了Objective-C 的指针和其他不安全访问的使用,舍弃了Objective C早期套用Smalltalk风格的语法,全面改为句点表示法(dot-notation)。Swift具备类型推导(type inference)。同时它提供了类似C++、C#中的名字空间(namespace)、泛型(generic)、运算符重载(operator overloading)。Swift被简单的形容为 “没有C的Objective-C”(Objective-C without the C)。Swift全面使用自动引用计数(ARC)来管理内存,取代Objective C的垃圾回收功能。在Objective-C中,强引用(strong reference)即为非ARC中的retain,而弱引用(weak reference)即为非ARC中的assign。为了解决循环引用的问题,Swift提供unowned,不能设定为optional types,不能加上问号(?)或惊叹号(!)。Xcode的调试机制针对Swift语言提供REPL(Read-Eval-Print Loop, 这是源自emacs的术语)环境,可以利用Swift语法来评估或于其他程序互动,使Swift编程具有类似Python或Ruby带有的交互性界面(Interactive Shell)。Swift不需要引入头文件(header file)或main()函数,不需要在每一行语句(statement)结尾加上分号。

语言创新之处
陈述句(statement)不需要用分号(;)结束,但分号可以作为一行上两个以上语句的分割符。
不需要头文件(Header files)。
注解方式 /* ... */ 嵌套,指注释里可以再有注释。
强类型与支持泛型编程。
类型推论或隐含类型(Type inference)。
函数成为第一等类型(first-class object),这意味着函数可以作为其他函数的参数和返回值。
运算符重载。运算符可在类内重新定义。
定义新的运算符。
字符串全方面支持 Unicode。
规避了C语言家族的易错行为:
1).不存在指针。
2).赋值语句没有返回值。若将if (i==0)误写成if (i=0),将造成编译时期错误。
3).在switch 的区块内不需要使用 break 语句。另外,case后面都需要有可执行的代码(C或C++可连续使用多个case而不需要额外的代码),否则将触发编译错误。
4).变量和常量必须初始化才能使用,而且数组(array)的边界必须明确确认。
5).溢出(overflows)的问题。C语言没有强制整数类型(signed integers)的界限,常常在触发执行时期错误。Swift通过整数类型的max或min属性获取最大值或最小值。

在开发iOS APP时有两种语言可以选择,Swift(Swift Programming Language)和 Objective-C(Objective-C Programming Language),它们是两种不同的编程语言,都被用于iOS和macOS等苹果平台的软件开发。两都区别如下:

1.年代:Objective-C是早期苹果平台上主要的编程语言,自1983年起就在苹果公司中使用,并于1988年首次发布。它成为iOS和macOS的主要编程语言直到Swift的推出。Swift是由苹果公司于2014年推出的新一代编程语言,旨在取代前者并提供更现代化和安全的开发体验。

2.语法:Objective-C是一种基于C语言的扩展,使用了面向对象编程的语法,同时引入了消息传递和动态运行时特性。Swift是一种全新的语言,其语法更简洁、现代化,更接近于其他现代编程语言。它抛弃了前者中繁琐的消息传递语法,并引入了可选类型、自动内存管理等新特性。

3.类型系统:Objective-C使用动态类型系统,这意味着变量的类型在运行时才确定。Swift采用静态类型系统,变量的类型在编译时就需要确定,这有助于提前发现潜在的类型错误。

4.内存管理:Objective-C使用手动引用计数(Manual Reference Counting,MRC)或自动引用计数(Automatic Reference Counting,ARC)来管理内存。Swift只支持自动引用计数(ARC),编译器会自动管理内存,开发者不需要手动处理引用计数。

5.兼容性:Objective-C代码可以与Swift代码无缝混合使用,这使得逐步迁移到Swift更容易。Swift代码不能直接调用前者中的一些高级特性,但是可以使用Objective-C的桥接机制来访问前者库和代码。

6.性能:在某些情况下,Objective-C可能稍微比Swift运行效率低,因为前者使用了动态运行时机制。Swift在一些情况下由于其静态类型和优化特性可能比Objective-C更快。

总的来说,Swift是一种现代化、安全性更高的编程语言,相较于Objective-C,它更易于学习和使用,具有更好的性能和更强大的特性。然而,由于Objective-C历史悠久,在某些老旧项目或特定的库和功能上,仍然会继续使用它。


最新版本:5.8
Swift 5.8 已经正式于2023年4月上旬发布,该版本包括改进开发者体验,改进 Swift 生态中的工具,包括 Swift-DocC、Swift Package Manager 和 SwiftSyntax,完善 Windows 支持 等等。

改进的 Result Builder 实现
在 Swift 5.8 中对 Result Builder 的实现进行了重做,以大幅提高编译时性能、代码补全结果和诊断能力。Swift 5.8 的 Result Builder 实现执行了更严格的类型推理,与 SE-0289: Result Builders 中的语义相符,这对一些依赖无效类型推理的现有代码有影响。

正如 2 月宣布的,《Swift 编程语言》一书已被转换为 Swift-DocC 并开源,随之而来的是对 Swift-DocC 本身的一些改进,其形式为 Option 指令,你可以用来改变你生成的文档的行为。Swift-DocC 还增加了一些新的指令来创建更多的动态文档页面,包括基于网格的布局和标签导航器。为了更进一步,现在可以通过颜色、字体和定制图标自定义你的文档页面的外观。导航也向前迈进了一步,有了快速导航,可以在项目中进行模糊的搜索。Swift-DocC 现在还支持记录对其他模块的类型的扩展。这是一个选择性功能,可以在使用 Swift-DocC 插件时添加 -include-extended-types 标志来启用。

Swift Package Manager
以下是 Swift 5.8 中对 Swift Package Manager 引入变化的一些亮点:
SE-0362:目标现在可以指定他们需要的即将到来的语言功能。Package.swift 清单语法已通过 API 进行了扩展,包括在目标层设置 enableUpcomingFeature 和 enableExperimentalFeature 标志。
SE-0378: 现在支持在与包注册表交互时进行令牌认证。swift package-registry 命令有两个新的子命令 login 和 logout,用于添加 / 删除注册表凭证。
现在允许公开一个仅由二进制目标组成的可执行产品,该目标由一个工件包支持。这允许将二进制可执行文件作为它们自己独立的软件包出售,独立于正在使用它们的插件。
在使用 5.8 或更高版本的工具的包中,Foundation 不再被隐式导入包清单中。如果使用 Foundation API,则需要明确导入该模块。

Swift Syntax
随着 SwiftSyntax 的 Swift 5.8 版本的发布,SwiftSyntax 包含一个完全重新编写的解析器,它完全由 Swift 实现,而不是依靠 C++ 解析器来生成 SwiftSyntax 树。虽然 Swift 编译器仍然使用用 C++ 实现的旧解析器,但最终目标是完全取代旧解析器。新的解析器有很多优点:
贡献或依赖 SwiftSyntax 现在就像其他 Swift 包一样容易,这大大降低了新的贡献者和采用者的准入门槛。
新的解析器是以错误恢复为主要目标设计的。它对解析错误的容忍度更高,产生的错误信息也更好。
SwiftSyntaxBuilder 允许使用结果构建器和字符串插值的混合方式,以声明的方式生成源代码。

Windows 平台
Swift 5.8 继续对 Windows 工具链进行增量改进。这个发布周期中的一些重要工作包括:
Windows 工具链减少了对环境变量的一些依赖。DEVELOPER_DIR 以前需要用来定位组件,现在不再需要了。这清理了安装程序,使我们能够更接近于按用户安装。
ICU 已经改为静态链接。这减少了需要分发的文件的数量,并减少了运输产品所需的依赖关系的数量。这是因为在 Swift 标准库中删除了 ICU 的依赖性,才得以实现。
支持 Windows 上 C++ 互操作的一些初步工作已被合并,并在工具链中提供。这包括对微软 C++ 运行时(msvcprt)进行模块化的工作。
vcruntime 模块已被重新命名为 visualc。这更好地反映了该模块,并为未来加强与 Windows 平台库的连接铺平了道路。
改善 Swift 包管理器中的路径处理的大量工作已被合并。这将有助于使 Swift 包管理器在 Windows 上更加强大,并改善与 SourceKit-LSP 的交互。
SourceKit-LSP 已经受益于一些改进。跨模块引用现在更加可靠,C/C++ 引用也得到了改善,这要归功于 SPM 中增强的路径处理,确保文件被正确识别。

更多详情可查看发行说明

最新版本:5.10
Swift 5.10 现已于2024年3月上旬发布,此版本在并发语言模型中实现了完全的数据隔离。公告称,“这一重要的里程碑经过了多年的积极开发,历经多个版本。”并发模型是在 5.5 中引入的,包括async/await、actors 和结构化并发 (structured concurrency)。Swift 5.7 引入了 Sendable 线程安全类型的基本概念,其值可以在任意并发上下文之间共享,而不会引入数据竞争的风险。现在 Swift 5.10 中,当启用完整的并发检查选项时,语言的所有区域都会在编译时强制执行完全数据隔离。

5.10 中的完全数据隔离为下一个主要版本 Swift 6 奠定了基础。6.0 编译器将提供新的、可选的 Swift 6 语言模式,该模式将默认强制执行完全数据隔离,项目团队将着手进行过渡消除所有用 Swift 编写的软件之间的数据竞争。5.10 会在某些情况下产生数据竞争警告,而在这些情况下,通过额外的编译器分析可以证明代码是安全的。Swift 6 版本的语言开发的一个主要重点是通过减少已证明安全的常见代码模式中的误报并发错误,来提高严格并发检查的可用性。

完全数据隔离
5.10 完善了语言各个角落的数据竞争安全语义,并修复了 Sendable 和 actor isolation checking 中的大量错误,以加强完整并发检查的保证。使用编译器 flag-strict-concurrency=complete 构建代码时,5.10 将在编译时诊断数据竞争的可能性,除非使用 explicit unsafe opt-out(例如 nonisolated(unsafe) 或 @unchecked Sendable)。

warning: expression is 'async' but is not marked with 'await'
    let model = MyModel.shared
    ^~~~~~~~~~~~~~
    await

解决数据竞争的可能修复方法有:
1) access MyModel.shared asynchronously using await
2) 使 MyModel.init 和 MyModel.shared 两者都 nonisolated,并将需要 main actor 的代码移到单独的隔离方法中,或
3) 将 useShared() 隔离到 @MainActor。

可以在 5.10 发行说明中查看更多详细信息。

Unsafe opt-outs
5.10 引入了一个新 nonisolated(unsafe)keyword,用于 opt out 对存储的属性和变量的 actor isolation checking。nonisolated(unsafe) 可用于任何形式的存储,包括存储属性、局部变量和全局/静态变量。

Swift 6 之前的语言演变
Swift 的下一个版本将是 Swift 6。鉴于 5.10 中的完整并发模型限制过多,团队目前正在积极开发几项 Swift Evolution 提议,以通过消除误报数据竞争错误来提高完整数据隔离的可用性。这项工作包括:当编译器确定没有并发访问的可能性时,取消对跨隔离边界传递 non-Sendable值的限制;为 functions 和 key-paths 提供更有效的 Sendable inference 等。可以在 Swift.org/swift-evolution 上找到将完善 Swift 6 的提案集。

更多详情可查看官方博客


官方主页:https://www.swift.org/