Python实战社群

Java实战社群

长按识别下方二维码,按需求添加

扫码关注添加客服

进Python社群▲

扫码关注添加客服

进Java社群

转自:掘金  CainLuo

https://juejin.cn/post/6928043538621923335

多个变量参数,改进隐式成员语法,结果构建器等。

Swift 5.4带来了一些巨大的编译改进,包括更好地完成带错误的表达式中的代码,以及增量编译的大提速。不过,它也增加了一些重要的新特性和改进,让我们在这里深入了解一下......

  • 小贴士:

    如果你想自己尝试代码样本,也可以下载这个作为Xcode Playground。

改进了隐式成员语法

SE-0287改进了Swift使用隐式成员表达式的能力,所以你可以制作它们的链子,而不是只支持一个单一的静态成员。

Swift一直以来都有能力使用隐式成员语法来处理简单的表达式,例如,如果你想在SwiftUI中给一些文本着色,你可以使用.red而不是Color.red。

struct ContentView1: View {var body: some View {Text("You're not my supervisor!").foregroundColor(.red)}
}

在Swift 5.4之前,这在更复杂的表达式中是行不通的。例如,如果你想让你的红色略微透明,你就需要这样写。

struct ContentView2: View {var body: some View {Text("You're not my supervisor!").foregroundColor(Color.red.opacity(0.5))}
}

从Swift 5.4开始,编译器能够理解多个链式成员,这意味着可以推断出Color类型。

struct ContentView3: View {var body: some View {Text("You're not my supervisor!").foregroundColor(.red.opacity(0.5))}
}

函数中的多变量参数

SE-0284引入了让函数、下标和初始化器使用多个变量参数的能力,只要变量参数后面的所有参数都有标签。在Swift 5.4之前,这种情况下只能有一个变量参数。

所以,有了这个改进,我们可以写一个函数,接受一个变量参数,存储足球比赛中进球的次数,再加上第二个变量参数,打出进球球员的名字。

func summarizeGoals(times: Int..., players: String...) {let joinedNames = ListFormatter.localizedString(byJoining: players)let joinedTimes = ListFormatter.localizedString(byJoining: times.map(String.init))print("\(times.count) goals where scored by \(joinedNames) at the follow minutes: \(joinedTimes)")
}

要调用该函数,提供两组值作为变量参数,确保第一个变量之后的所有参数都有标签。

summarizeGoals(times: 18, 33, 55, 90, players: "Dani", "Jamie", "Roy")

结果生成器

函数构建器在Swift 5.1中非正式地出现了,但在Swift 5.4之前,它们作为SE-0289正式通过了Swift进化提案过程,以便进行讨论和完善。作为这个过程的一部分,它们被重新命名为结果构建器以更好地反映它们的实际目的,甚至获得了一些新的功能。

首先是最重要的部分:结果构建器允许我们通过在我们选择的序列中一步步地创造一个新的价值。它们为SwiftUI的视图创建系统的很大一部分提供了动力,所以当我们拥有一个内部有各种视图的VStack时,Swift会默默地将它们归为一个内部的TupleView类型,这样它们就可以作为VStack的一个子代来存储--它将一个视图序列变成了一个视图。

结果构建器应该有自己的详细文章,但我至少想给你一些小的代码示例,这样你就可以看到它们的运作。

下面是一个返回单个字符串的函数。

func makeSentence1() -> String {"Why settle for a Duke when you can have a Prince?"
}print(makeSentence1())

这很好用,但如果有几个字符串我们想连接在一起呢?就像SwiftUI一样,我们可能想把它们都单独提供,然后让Swift来解决。

// This is invalid Swift, and will not compile.
// func makeSentence2() -> String {
//     "Why settle for a Duke"
//     "when you can have"
//     "a Prince?"
// }

就其本身而言,这段代码是行不通的,因为Swift不再理解我们的意思。然而,我们可以创建一个结果生成器,它可以理解如何使用我们想要的任何转换将几个字符串转换为一个字符串,就像这样。

@resultBuilder
struct SimpleStringBuilder {static func buildBlock(_ parts: String...) -> String {parts.joined(separator: "\n")}
}

尽管这只是少量的代码,但有很多需要解压。

  • @resultBuilder属性告诉SwiftUI以下类型应该被视为结果构建器。

    以前这种行为是通过@_functionBuilder实现的,它有一个下划线来表明这不是为一般使用而设计的。

  • 每个结果构建器都必须提供至少一个名为buildBlock()的静态方法,该方法应该接收某种数据并对其进行转换。

    上面的例子是接收零个或多个字符串,将它们连接起来,然后以单个字符串的形式发送回来。

  • 最终的结果是,我们的SimpleStringBuilder结构变成了一个结果构建器,这意味着我们可以在任何需要它的字符串连接能力的地方使用@SimpleStringBuilder。

没有什么可以阻止我们直接使用SimpleStringBuilder.buildBlock(),就像这样。

let joined = SimpleStringBuilder.buildBlock("Why settle for a Duke","when you can have","a Prince?"
)print(joined)

然而,由于我们在SimpleStringBuilder结构中使用了@resultBuilder注解,我们也可以将其应用到函数中,就像这样。

@SimpleStringBuilder func makeSentence3() -> String {"Why settle for a Duke""when you can have""a Prince?"
}print(makeSentence3())

请注意,我们不再需要每个字符串末尾的逗号--@resultBuilder通过使用SimpleStringBuilder自动将makeSentence()中的每个语句转换为单个字符串。

在实践中,结果生成器能够做得更多,通过向你的生成器类型添加更多的方法来完成。例如,我们可以通过添加两个额外的方法来为我们的SimpleStringBuilder添加if/else支持,这两个方法描述了我们要如何转换数据。在我们的代码中,我们根本不想转换我们的字符串,所以我们可以直接把它们送回去。

@resultBuilder
struct ConditionalStringBuilder {static func buildBlock(_ parts: String...) -> String {parts.joined(separator: "\n")}static func buildEither(first component: String) -> String {return component}static func buildEither(second component: String) -> String {return component}
}

我知道,看起来我们几乎没有做任何工作,但现在我们的函数能够使用条件。

@ConditionalStringBuilder func makeSentence4() -> String {"Why settle for a Duke""when you can have"if Bool.random() {"a Prince?"} else {"a King?"}
}print(makeSentence4())

同样,我们也可以通过在构建器类型中添加 buildArray() 方法来添加对循环的支持。

@resultBuilder
struct ComplexStringBuilder {static func buildBlock(_ parts: String...) -> String {parts.joined(separator: "\n")}static func buildEither(first component: String) -> String {return component}static func buildEither(second component: String) -> String {return component}static func buildArray(_ components: [String]) -> String {components.joined(separator: "\n")}
}

现在我们可以使用for循环。

@ComplexStringBuilder func countDown() -> String {for i in (0...10).reversed() {"\(i)…"}"Lift off!"
}print(countDown())

这感觉几乎就像魔法一样,因为结果构建器系统几乎为我们做了所有的工作,尽管我们的例子已经相当简单,但我希望你能感受到结果构建器给Swift带来的非凡力量。

值得补充的是,Swift 5.4扩展了结果构建器系统,支持属性被放置在存储的属性上,这将自动调整结构的隐式成员初始化器来应用结果构建器。

这对于使用结果构建器的自定义SwiftUI视图特别有帮助,比如这个视图。

struct CustomVStack<Content: View>: View {@ViewBuilder let content: Contentvar body: some View {VStack {// custom functionality herecontent}}
}

如果你想看到更多高级的、实际操作的结果构建器的例子,你应该查看GitHub上的Awesome Function Builders仓库。

本地函数现在支持重载

SR-10069要求能够在本地上下文中重载函数,这实际上意味着嵌套函数现在可以重载,这样Swift就可以根据使用的类型来选择运行哪个函数。

例如,如果我们想制作一些简单的 cookie,我们可能会写这样的代码。

struct Butter { }
struct Flour { }
struct Sugar { }func makeCookies() {func add(item: Butter) {print("Adding butter…")}func add(item: Flour) {print("Adding flour…")}func add(item: Sugar) {print("Adding sugar…")}add(item: Butter())add(item: Flour())add(item: Sugar())
}

在Swift 5.4之前,三个add()方法只有在没有嵌套在makeCookies()里面的情况下才能被重载,但从Swift 5.4开始,这种情况下也支持函数重载。

现在支持本地变量的属性包装器了 属性包装器最早是在Swift 5.1中引入的,作为一种以简单、可重用的方式为属性附加额外功能的方式,但在Swift 5.4中,它们的行为得到了扩展,支持在函数中作为局部变量使用。

例如,我们可以创建一个属性包装器,确保其值永远不会低于零。

@propertyWrapper struct NonNegative<T: Numeric & Comparable> {var value: Tvar wrappedValue: T {get { value }set {if newValue < 0 {value = 0} else {value = newValue}}}init(wrappedValue: T) {if wrappedValue < 0 {self.value = 0} else {self.value = wrappedValue}}
}

而从Swift 5.4开始,我们可以在一个常规函数里面使用这个属性包装器,而不仅仅是附加到一个属性上。例如,我们可以写一个游戏,在这个游戏中,我们的玩家可以获得或失去分数,但他们的分数绝对不能低于0。

func playGame() {@NonNegative var score = 0// player was correctscore += 4// player was correct againscore += 8// player got one wrongscore -= 15// player got another one wrongscore -= 16print(score)
}

软件包现在可以声明可执行目标

SE-0294 为使用 Swift 包管理器的应用程序增加了一个新的目标选项,允许我们明确声明一个可执行目标。

这对于想要使用 SE-0281(使用 @main 来标记你的程序的入口点)的人来说特别重要,因为它与 Swift 包管理器玩得并不好--它总是会寻找 main.swift 文件。

通过这次修改,我们现在可以删除main.swift而使用@main来代替。注意:你必须在你的Package.swift文件中指定// swift-tools-version:5.4才能获得这个新功能。

自己尝试

Swift 5.4可以通过Xcode 12.5获得,Xcode 12.5于2021年2月1日进入测试版。如果你还没有升级到macOS Big Sur,你将无法安装Xcode 12.5,所以你应该从https://swift.org/download/ 下载一个Swift 5.4工具链--你可以将其安装到Xcode 12.4和更早的版本中。

你最期待Swift 5.4的哪些功能?

程序员专栏 扫码关注填加客服 长按识别下方二维码进群

近期精彩内容推荐:  

 华为正式宣布养猪,网友:支持华为自救!

 入职腾讯第九年,我辞职了!

 Windows蓝屏为什么是蓝底白字?

 955 互联网公司白名单来了!

在看点这里好文分享给更多人↓↓

Swift 5.4 有什么新功能?相关推荐

  1. Swift 3有什么新功能?

    介绍 今年9月,Apple正式发布了其新编程语言Swift 3的最新版本.就像去年的Swift 2一样,该版本包含许多新功能和改进,这使使用Swift进行编程变得更加出色! 从8.0版开始,Xcode ...

  2. swift4 linux,Swift 4正式发布,新功能概览

    Swift最新的主要版本提供了针对语言本身以及标准库的大量改动和更新,最重要的变化包括新增的String功能.扩展集合.归档和序列化等. Swift 4中,String已全面遵循Collection协 ...

  3. Swift 3.1 的一些新特性

    Swift 3.1 的一些新特性 推荐序 本文来自泊学的投稿,介绍了 Swift 3.1 的新特性,感谢泊学授权发表.以下为文章正文. 正文 Apple 终于发布了Xcode 8.3以及Swift 3 ...

  4. ios设计登录功能_亲爱的产品设计师,这是iOS 14的新功能

    ios设计登录功能 On June 22, 2020 Apple previewed iOS 14 for the first time. As always there are quite some ...

  5. TIOBE 3月榜单:新功能将加入,C语言仍高居榜首

    喜欢就关注我们吧! TIOBE 公布了 2021 年 3 月的编程语言排行榜. 本月 TIOBE 指数没有什么有趣的变化.因此,TIOBE CEO Paul Jansen 表示,其打算透露一些近期将加 ...

  6. 战神4 幕后花絮 概念艺术_Java 9幕后花絮:新功能从何而来?

    战神4 幕后花絮 概念艺术 找出Java幕后发生的事情,以及新功能如何实现 在上一篇文章中,我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能,并简要提到了将新功能添加到下一个版本之前要经历 ...

  7. Java 9幕后花絮:新功能从何而来?

    找出Java幕后发生的事情,以及新功能如何实现 在上一篇文章中,我们介绍了即将发布的Java 9版本的新功能和尚待解决的功能,并简要提到了将新功能添加到下一个版本之前要经历的过程. 由于此过程几乎影响 ...

  8. Swift 3到5.1新特性整理

    本文转载自:https://hicc.me/whats-new-in-swift-3-to-5-1/,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有. Hipo 2.0 重写从 Swif ...

  9. openstack 功能_2016年OpenStack的新功能:看一下Newton版本

    openstack 功能 OpenStack的发布周期为六个月,每个发行版都有一个代号,名称以字母的连续字母开头. 10月7日,OpenStack Newton发布了. 让我们看一下OpenStack ...

最新文章

  1. Codeforces Round #360 E
  2. HarmonyOS之深入解析图像的位图操作和属性解码
  3. 对基于消息队列的Activiti异步执行器进行基准测试
  4. html5 打包ios.上架,iOS帮客户打包App上架的正确姿势
  5. windows xp 创建 Oracle(11G)数据库实例时写入系统日志失败解决方案
  6. Bootstrap框架(二)
  7. QT生成在Windows下有图标的exe文件(IDE=QT Creator)
  8. 人工神经网络到底能干什么?到底在干什么?
  9. 算法学习之路|到底买不买
  10. php 字符串中 数组变量,PHP返回变量或数组的字符串表示:var_export()
  11. 测绘地物的识别:建筑上怎么样区别挑廊、走廊、檐廊
  12. C++利用opencv 按顺序遍历文件夹图片
  13. 03-Spark MLib
  14. 【python】在图片上绘画
  15. 怎样判断小红书被限流?小红书被限流有这几大表现
  16. 计算机工程研究生美国专业排名,美国计算机研究生专业排名
  17. 高德地图完整功能的html,揭秘高德地图八大不为人知的强大功能
  18. 数据仓库数据存储与处理
  19. 关于oracle中ora-00600的报错
  20. 南京邮电大学2013年硕士研究生招生复试及同等学力加试参考书目

热门文章

  1. html设置发光字体制作,CSS3制作炫酷的自定义发光文字
  2. java SSM框架使用WebSocket推送视频流
  3. 初学Java基础学习——抽象类和接口的区别
  4. 如何制造一个Android智能手机
  5. python3连接oracle教程_python3 连接oracle
  6. gta5怎么设置画质最好_GTA5 PC版2G显卡设置最高画质心得 GTA5怎么设置画质
  7. 宇视雷视工勘指导(卡口电警篇)
  8. pat甲级什么水平_盘它!!!|PAT考试正式开启
  9. 软文营销怎样做到精准引流?成功的软文营销有这些特点
  10. 辗转相除法与更相减损术(求最大公约数)