Swift 5.9 有哪些新特性(一)

这篇具有很好参考价值的文章主要介绍了Swift 5.9 有哪些新特性(一)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Swift 5.9 有哪些新特性(一)

前言

虽然 Swift 6 已经在地平线上浮现,但 5.x 版本仍然有很多新功能-更简单的 if 和 switch 用法、宏、非可复制类型、自定义 actor 执行器等等都将在 Swift 5.9 中推出,再次带来了一个巨大的更新。

在本文中,将介绍这个版本中最重要的变化,提供代码示例和解释,以便可以自行尝试。需要在 Xcode 14 中安装最新的 Swift 5.9 工具链,或者使用 Xcode 15 beta。

if 和 switch 表达式

Swift 5.9 有哪些新特性(一)
SE-0380 引入了在多种情况下将 if 和 switch 用作表达式的能力。这会产生一些在一开始可能会让人感到惊讶的语法,但总体上它确实帮助减少了语言中一些额外的语法。

作为一个简单的例子,我们可以根据条件将变量设置为“ Pass ”或“ Fail ”:

let score = 800
let simpleResult = if score > 500 { "Pass" } else { "Fail" }
print(simpleResult)

或者可以使用 switch 表达式来获取更广泛的值,就像下面这样:

let complexResult = switch score {
    case 0...300: "Fail"
    case 301...500: "Pass"
    case 501...800: "Merit"
    default: "Distinction"
}

print(complexResult)

不需要在某个地方分配结果以使用这种新的表达式语法,实际上它与 Swift 5.1 的 SE-0255 非常搭配,该特性允许我们在返回一个值的单表达式函数中省略 return 关键字。

所以,由于 if 和 switch 现在都可以作为表达式使用,我们可以编写一个像这样的函数,在所有四种可能的情况下都不使用 return 关键字:

func rating(for score: Int) -> String {
    switch score {
    case 0...300: "Fail"
    case 301...500: "Pass"
    case 501...800: "Merit"
    default: "Distinction"
    }
}

print(rating(for: score))

你可能会认为这个特性使得 if 更像三元条件运算符,至少在某种程度上是对的。例如,我们可以像这样编写之前的简单 if 条件:

let ternaryResult = score > 500 ? "Pass" : "Fail"
print(ternaryResult)

然而,它们并不完全相同,特别是有一个地方可能会让你困惑 - 你可以在下面的代码中看到:

let customerRating = 4
let bonusMultiplier1 = customerRating > 3 ? 1.5 : 1
let bonusMultiplier2 = if customerRating > 3 { 1.5 } else { 1.0 }

这两个计算都产生了一个值为 1.5 的 Double,但是注意每个计算的备选值:对于三元选项,是写了 1,而对于 if 表达式,是写了 1.0。

这样做是有原因的:当使用三元运算符时,Swift 同时检查两个值的类型,因此自动将 1 视为 1.0,而对于 if 表达式,两个选项是独立进行类型检查的:如果我们在一个情况下使用 1.5,在另一个情况下使用 1,那么我们将返回一个 Double 和一个 Int,这是不允许的。

Value 和 Type 参数包

Swift 5.9 有哪些新特性(一)

SE-0393、SE-0398 和 SE-0399 结合在一起形成了 Swift 中使用可变泛型的一系列改进的复杂结构。

这是一个相当高级的特性,用一种能够吸引大多数人注意的方式概括一下:这几乎肯定意味着 Swift 中的旧的 10 个视图限制即将消失。

这些提案解决了 Swift 中一个重要的问题,即泛型函数需要指定数量的类型参数。这些函数仍然可以接受可变参数,但最终仍然必须使用相同的类型。

举个例子,我们可以有三个不同的结构体,表示程序的不同部分:

struct FrontEndDev {
    var name: String
}

struct BackEndDev {
    var name: String
}

struct FullStackDev {
    var name: String
}

在实际情况中,这些结构体可能具有更多使它们成为独特类型的属性,但你可以理解这个例子 - 存在三种不同的类型。

我们可以这样创建这些结构体的实例:

let johnny = FrontEndDev(name: "Johnny Appleseed")
let jess = FrontEndDev(name: "Jessica Appleseed")
let kate = BackEndDev(name: "Kate Bell")
let kevin = BackEndDev(name: "Kevin Bell")

let derek = FullStackDev(name: "Derek Derekson")

当需要开始工作时,我们可以使用以下简单的函数将开发人员配对:

func pairUp1<T, U>(firstPeople: T..., secondPeople: U...) -> ([(T, U)]) {
    assert(firstPeople.count == secondPeople.count, "You must provide equal numbers of people to pair.")
    var result = [(T, U)]()

    for i in 0..<firstPeople.count {
        result.append((firstPeople[i], secondPeople[i]))
    }

    return result
}

该函数使用两个可变参数接收一组第一组人和一组第二组人,并将它们作为数组返回。

现在我们可以使用它将可以一起开展后端和前端工作的程序员配对:

let result1 = pairUp1(firstPeople: johnny, jess, secondPeople: kate, kevin)

到目前为止,这些都是老的内容,现在我们开始进入有趣的部分:假设 Derek 是一个全栈开发人员,可以作为后端开发人员或前端开发人员工作。然而,如果我们尝试使用 johnny, derek 作为第一个参数,Swift 将拒绝构建我们的代码 - 它需要所有第一组人和第二组人的类型相同。

解决这个问题的一种方法是使用 Any 抛弃所有类型信息,但是参数包使我们能够更加优雅地解决这个问题。

刚开始时,语法可能会有点复杂,所以我先展示代码,然后再解释它。请看以下代码:

func pairUp2<each T, each U>(firstPeople: repeat each T, secondPeople: repeat each U) -> (repeat (first: each T, second: each U)) {
    return (repeat (each firstPeople, each secondPeople))
}

这里有四个独立的部分,我们逐一来解释:

  • <each T, each U> 创建了两个类型参数包,T 和 U。
  • repeat each T 是一个参数包展开,它将参数包展开为实际值 - 这相当于 T...,但避免了使用 ... 作为运算符时产生的某些混淆。
  • 返回类型表示我们将返回 T 和 U 的成对程序员元组的重复。
  • 我们的 return 关键字才是真正起作用的地方:它使用参数包展开表达式从 T 中取一个值,从 U 中取一个值,将它们放在返回值中组合起来。

返回类型自动确保的 T 和 U 类型具有相同的结构 - 具有相同数量的内部项。因此,与我们在第一个函数中使用的 assert() 不同,如果尝试传入两组不同大小的数据,Swift 将简单地发出编译器错误。

有了这个新函数,我们现在可以将 Derek 与其他开发人员配对,例如:

let result2 = pairUp2(firstPeople: johnny, derek, secondPeople: kate, kevin)

实际上,我们实现了一个简单的 zip() 函数,这意味着我们可以写出这样的荒谬代码:

let result3 = pairUp2(firstPeople: johnny, derek, secondPeople: kate, 556)

它尝试将 Kevin 与数字 556 配对,显然是没有意义的。这就是参数包的优势所在,因为我们可以定义以下协议:

protocol WritesFrontEndCode { }
protocol WritesBackEndCode { }

然后添加一些遵循关系:

  • FrontEndDev 应该遵循 WritesFrontEndCode
  • BackEndDev 应该遵循 WritesBackEndCode
  • FullStackDev 应该同时遵循 WritesFrontEndCodeWritesBackEndCode

现在,可以给我们的类型参数包添加约束:

func pairUp3<each T: WritesFrontEndCode, each U: WritesBackEndCode>(firstPeople: repeat each T, secondPeople: repeat each U) -> (repeat (first: each T, second: each U)) {
    return (repeat (each firstPeople, each secondPeople))
}

这意味着只有合理的配对才能发生 - 无论是否是全栈开发人员,我们始终会得到一个能够编写前端代码的人与一个能够编写后端代码的人配对。

为了让你更容易理解,我们在 SwiftUI 中也有类似的情况。我们经常希望能够创建具有多个子视图的视图,如果我们只使用单一的视图类型(例如 Text),那么类似于 Text... 的写法将非常好用。但是,如果我们希望有一些文本,然后是图像,然后是按钮等等 - 任何非均匀布局都将不可能实现。

尝试使用 AnyView... 或类似的方式来抹除类型会丢失所有类型信息,因此在 Swift 5.9 之前,通过创建大量函数重载来解决此问题。例如,SwiftUI 的视图构建器具有 buildBlock() 重载,可以组合两个视图、三个视图、四个视图等等,一直到 10 个视图 - 但没有更多,因为它们需要划定一个限制。

因此,在 SwiftUI 中存在 10 个视图的限制。希望这个限制在即将发布的 Swift 5.9 中消失。文章来源地址https://www.toymoban.com/news/detail-486282.html

到了这里,关于Swift 5.9 有哪些新特性(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Swift的高级语法特性,如可选类型、闭包、枚举、泛型、协议、扩展等

    Swift是一门现代化的编程语言,具有许多高级语法特性,下面我们来逐一介绍。 1. 可选类型(Optional) Swift中的可选类型是一种特殊的类型,它可以表示一个值是存在或不存在的。在声明一个可选类型时,需要在类型名称后面加上一个问号(?)来表示这个类型是可选的。例如

    2024年02月04日
    浏览(30)
  • 06-3_Qt 5.9 C++开发指南_多窗体应用程序的设计(主要的窗体类及其用途;窗体类重要特性设置;多窗口应用程序设计)

    常用的窗体基类是QWidget、QDialog 和QMainWindow,在创建 GUI应用程序时选择窗体基类就是从这 3 个类中选择。QWidget 直接继承于 QObject,是 QDialog 和 QMainWindow 的父类,其他继承于 QWidget 的窗体类还有 QSplashScreen、QMdiSubWindow和QDesktopWidget。另外还有一个类QWindow,它同时从 QObject 和Q

    2024年02月13日
    浏览(72)
  • 掌握哪些测试技术才能说自己已经学成了?

    一、过硬的基础能力 其实所有的测试大佬都是从底层基础开始的,随着时间,经验的积累慢慢变成大佬。要想稳扎稳打在测试行业深耕,成为测试大牛,首当其冲的肯定就是拥有过硬的基础,所有的基础都是根基,后期所有的发展和提升都是基于测试基础铺垫的。 所以核心

    2024年02月07日
    浏览(37)
  • 当年很流行,现在已经淘汰的前端技术有哪些?

    近几年,前端技术真可谓是飞速发展,不断有新的技术涌现,爆火的前端框架 Astro,前端运行时 Bun,构建工具 Vite 等都给前端提供了强大动力。当然,也有很多前端技术随着技术的发展不再需要使用,有了更好的替代方案。本文就来盘点一下那些不再流行的前端技术,以及对

    2024年02月08日
    浏览(43)
  • css3有哪些新特性?(包含哪些模块)

    css3有哪些新特性?包含哪些模块?以下是整理的21个css3新特性: 1.新增选择器 p:nth-child(n){color: rgba(255, 0, 0, 0.75)} 2.新增伪元素 ::before 和 ::after 3.弹性盒模型 display: flex; 4.多列布局 column-count: 5; 5.媒体查询 @media (max-width: 480px) {.box: {column-count: 1;}} 6.个性化字体 @font-face{font-family:

    2024年02月11日
    浏览(36)
  • InnoDB有哪些特性

    事务支持:InnoDB支持ACID(原子性、一致性、隔离性和持久性)事务,可以保证数据的完整性和一致性。它使用多版本并发控制(MVCC)来实现事务的隔离性,支持读已提交和可重复读两种隔离级别。 行级锁定:InnoDB使用行级锁定来实现并发控制,可以提高并发性能。它支持多

    2024年02月14日
    浏览(24)
  • CSS3有哪些新特性

    CSS3引入了很多新特性,比如: 1. 选择器:CSS3引入了新的选择器,如伪类选择器、伪元素选择器等,使得选择元素更加灵活和精确。 2. 边框圆角:CSS3允许通过 border-radius 属性为元素的边框添加圆角,创建圆形、椭圆形或具有不同角度的矩形边框。 3. 盒阴影:使用 box-shadow 属

    2024年02月09日
    浏览(25)
  • 【全面】CSS3新增了哪些新特性?

    目录 一、选择器的扩展 1.  属性选择器 2. 伪类选择器 3. 伪元素选择器 二、盒子模型的增强  1. box-sizing属性 2. 边框圆角(border-radius) 3. 盒阴影(box-shadow) 三、过渡和动画效果 1. 过渡效果 2. 动画效果 四、响应式布局 1. 媒体查询(media query) 2. 弹性布局(Flexbox)

    2024年02月07日
    浏览(29)
  • JDK 新版本中都有哪些新特性?

    JDK 8 推出了 Lambda 表达式、Stream、Optional、新的日期 API 等 JDK 9 中推出了模块化 JDK 10 中推出了本地变量类型推断 JDK 12 中增加了 switch 表达式 JDK 13 中增加了 text block JDK 14 中增加了 Records JDK 15 中增加了封闭类 JDK 17 中扩展了 switch 模式匹配 JDK 19 中增加了协程 Java 8引入了Stream

    2024年02月11日
    浏览(25)
  • es6有哪些新特性?用法和案例

    目录 箭头函数 模板字符串  解构赋值 Promise  async/await 箭头函数使用 = 符号定义,可以更简洁地书写函数并且自动绑定 this 。比如: 箭头函数通常用在回调函数中,例如: 模板字符串是一种新的字符串格式,可以包含变量、表达式和换行符。通过使用占位符 ${} 可以插入变

    2024年02月06日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包