对于 ‘Swift 5.3 的新功能’,你了解吗?

Swift 5.3 的新功能,你了解吗?

支持跨平台,多个尾随闭包,多模式 catch 子句等等

Swift 5.3 的发布流程始于三月底,直到最近才进入最后的开发阶段。该版本的主要目标之一是扩展语言支持 Windows 和 Linux 平台。

苹果公司也非常注重改善语言的综合性能,以提升 SwiftUI 和 iOS 中机器学习的表现。让我们来仔细研究一下即将发布的新版本中有哪些重要更新。

资料分享:资料内容包括逆向安防、算法、架构设计、Swift、多线程,网络进阶,还有底层、音视频、Flutter等等

作为开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个 我的iOS交流群:761407670,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!

多个尾随闭包

SE-0279 提案中提出了新的尾随闭包语法,使您可以用更容易理解的方式将多个闭包作为函数的参数进行调用。这是一种更加强大的语法糖,可最大程度地减少在函数签名中使用过多括号。

它允许您在初始未带标签的闭包之后附加几个带标签的闭包。以下示例演示了这种用法:

//old
UIView.animate(withDuration: 0.5, animations: {
  self.view.alpha = 0
}, completion: { _ in
  self.view.removeFromSuperview()
})

//new multiple trailing closures
UIView.animate(withDuration: 0.5) {
            self.view.alpha = 0
        } completion: { _ in
            self.view.removeFromSuperview()
        }
复制代码

上面的语法变化能让 SwiftUI 视图更容易编写。

多模式 catch 子句

当前,do-catch 语句中的每个 catch 子句只能包含一个模式。要解决此问题,开发人员在 catch 语句的主体中最好使用 swtich case 语句,但这样会增加嵌套和重复的代码。

SE-0276 是另一个很好的改进,它允许 catch 字句进行模式匹配。Catch 子句将允许用户指定逗号分隔的模式列表,并将变量与 catch 主体绑定,就像 switch 语句一样。下面是例子:

enum NetworkError: Error {
    case failure, timeout
}

//old
func networkCall(){
  do{
    try someNetworkCall()
  }catch NetworkError.timeout{
    print("timeout")
  }catch NetworkError.failure{
    print("failure")
  }
}

//new
func networkCall(){
  do{
    try someNetworkCall()
  }catch NetworkError.failure, NetworkError.timeout{
    print("handle for both")
  }
}
复制代码

多模式 catch 子句能让代码清晰简洁。

实现枚举类型的比较功能

到目前为止,比较两个枚举类型还不是一件容易的事。首先必须遵守 Comparable 协议,然后实现 static fun \< 方法来决定一个枚举类型的原始值是否小于另一个枚举类型的原始值。(对于 > 的情况反之亦然)。

值得庆幸的是,在 SE-0266 中,我们可以让枚举类型遵守 Comparable 协议而不必显式地实现它,只需保证枚举是标准类型。如果枚举类型没有设置关联值,enums 会根据声明的语义顺序进行比较。

下面是枚举类型排序的例子:

enum Brightness: Comparable {
    case low(Int)
    case medium
    case high
}

([.high, .low(1), .medium, .low(0)] as [Brightness]).sorted()
// [Brightness.low(0), Brightness.low(1), Brightness.medium, Brightness.high]
复制代码

枚举 case 与协议相匹配

Swift 中协议匹配模型是非常严格的,其中规定,与协议有着相同名称和参数的枚举 case 是不匹配的。我们只能手动实现,如下所示:

protocol DecodingError {
  static var fileCorrupted: Self { get }
  static func keyNotFound(_ key: String) -> Self
}

enum JSONDecodingError: DecodingError {
  case _fileCorrupted
  case _keyNotFound(_ key: String)
  static var fileCorrupted: Self { return ._fileCorrupted }
  static func keyNotFound(_ key: String) -> Self { return ._keyNotFound(key) }
}
复制代码

SE-0280 中取消了此限制,以便在协议中的名称与参数和枚举 case 相同时,枚举 case 可以直接与协议相匹配。

protocol DecodingError {
  static var fileCorrupted: Self { get }
  static func keyNotFound(_ key: String) -> Self
}
enum JSONDecodingError: DecodingError {
  case fileCorrupted
  case keyNotFound(_ key: String)
}
复制代码

self 不需要在每处都显式使用

SE-0269 提案中允许我们在不需要的时候省略 self。之前,当我们从闭包外部捕获值时,必须在闭包中使用 self。现在,当循环引用不太可能发生时,self 将会隐式存在。

下面的例子展示了这个更新:

struct OldView: View {

    var body: some View {
        Button(action: {
            self.sayHello()
        }) {
            Text("Press")
        }
    }

    func sayHello(){}
}

struct NewView: View {

    var body: some View {
        Button {
            sayHello()
        } label: {
            Text("Press")
        }
    }

    func sayHello(){}
}
复制代码

使用 SwiftUI 的开发人员会很乐意接受这一点。因为视图保存在值类型的结构体中,所以不会发生循环引用。

基于类型的程序入口

SE-0281 中允许我们使用新的 @main 属性,它可以定义 app 的入口。用属性对结构体或类进行标记能够保证它是程序进入的位置,所以你不必手动调用 AppDelegate.main()

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
static func main() {
        print("App will launch & exit right away.")
    }
}
复制代码

我们可以认为,在以后的版本中将弃用旧版本中特定域的属性 @UIApplicationMain@NSApplicationMain,而推荐使用 @main

where 字句在泛型声明上下文中的变化

到目前为止,where 字句不能在泛型上下文内嵌声明。比如,如果你在方法中添加 where 限制,编译器会抛出错误。要解决这个问题,我们必须创建单独的扩展来处理特定的 where 子句。

SE-0267 中,只要引用了泛型参数,我们就可以实现带有 where 字句的方法。下面是一个简短的代码片段:

struct Base<T> {
    var value : T 
}

extension Base{

  func checkEquals(newValue: T) where T : Equatable{...}
  func doCompare(newValue: T) where T : Comparable{...}

}
复制代码

通过在成员声明上允许 where 子句,我们可以轻松创建更短,更简洁的通用接口,而不用创建单独的扩展。

对集合中非连续元素的新操作

当前的版本中,访问集合中连续范围的元素很简单。对于数组,您只需用 [startIndex ... endIndex] 访问。

SE-0270 中介绍了一种叫做 RangeSet 的新类型,它可以获取不连续索引的集合,

var numbers = Array(1...15)

// Find the indices of all the even numbers
let indicesOfEvens = numbers.subranges(where: { $0.isMultiple(of: 2) })

// Find the indices of all multiples of 3
let multiplesofThree = numbers.subranges(where: { $0.isMultiple(of: 3) })

let combinedIndexes = multiplesofThree.intersection(indicesOfEvens)
let sum = numbers[combinedIndexes].reduce(0, +)
//Sum of 6 + 12 = 18
复制代码

使用 RangeSet,我们可以对集合做很多计算和操作。例如,通过使用 moveSubranges 函数,我们可以在数组中移动一系列索引。这样我们可以很容易将数组中的所有偶数移动到数组的开头:

let rangeOfEvens = numbers.moveSubranges(indicesOfEvens, to: numbers.startIndex)
// numbers == [2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15]
复制代码

完善 didSet 语义

之前,无论属性的引用是否有新的赋值,didSet 属性观察器的 getter 方法总是会被调用来检索 oldValue

这个机制可能对变量影响不大,但是对于大型数组,会分配存储空间并加载未使用的值,这个过程会影响程序性能。

SE-0268 中提出,仅在需要时才会加载 oldValue,这将提升 didSet 属性观察器的效率。而且,如果只实现了 didSet 而没有实现 willSet,更新也会正常进行。

下面是改进版 didSet 的例子:

class A {
    var firstArray = [1,2,3] {
        didSet { print("didSet called") }
    }

    var secondArray = [1,2,3,4] {
        didSet { print(oldValue) }
    }
}

let a = A()
// This will not call the getter to fetch the oldValue of firstArray
a.firstArray = [1,2]
// This will call the getter to fetch the oldValue of secondArray
a.secondArray = [1]
复制代码

Float16 新类型

SE-0277 提出了 Float16 —— 半精度浮点类型。随着近年来机器学习在移动设备上的出现,苹果公司在这一领域表现了其雄心壮志。Float16 通常用于移动设备上的 GPU 计算,并作为 ML 程序中权重的压缩格式。

let f16: Float16 = 7.29
复制代码

总结

我们已经总结了 Swift 5.3 语言重要的新功能,Swift 包管理器也进行了很多改进。让我们快速浏览一下它们:

  • SE-0271 允许您将资源(图像,数据文件等)添加到 Swift 包中。
  • SE-0278 可以添加本地化资源。
  • SE-0272 允许您在软件包管理器中以二进制格式集成闭源依赖(例如 Firebase)。
  • SE-0273 使您可以有条件地为不同的目标平台指定依赖管理器。

您可以在这个博客下载 Swift 的 Linux 发行版。或者您可以直接访问 Swift 的官网快速浏览 Swift 5.3 的快照版本。

本文结束。谢谢阅读。

分享:资料内容包括逆向安防、算法、架构设计、Swift、多线程,网络进阶,还有底层、音视频、Flutter等等

作为开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个 我的iOS交流群:761407670,不管你是小白还是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 大家一起交流学习成长!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容