Swift 5.9 新特性:consume

前言

在 Swift 中,是使用引用计数和 copy-on-wirte 的机制来管理内存,通常情况下,开发者只管使用即可,不用太关心内存相关。但对于一些性能敏感的代码来说,开发者可能会希望在语言层面上能够控制减少 retain、release 的调用。比如下面的代码:

swift 复制代码
func test() {
  var x: [Int] = [1, 3, 4]
  doStuffUniquely(with: x)
  x = []
}

func doStuffUniquely(with value: [Int]) {
  var newValue = value
  newValue.append(42)
  print(newValue)
}

上述代码中,变量 x 存储的是一个整型的数组。然后将其当做参数传递给了 doStuffUniquely(),接着在 doStuffUniquely() 函数体内部对 value 进行了数据处理。最后,x 被清空。

再将 x 传递给 doStuffUniquely() 的时候应该存在一种机制将 x 的数据所有权也转交过去。因为在 test() 中的后续代码中也并没有对 x 的数据进行使用。

现有的代码会存在一定的性能浪费,因为在 doStuffUniquely() 中的 var newValue = value 执行时会进行数组内容的 copy-on-wirte,而且当 doStuffUniquely() 函数执行完之后, newValue 因为作用域的原因而被释放,从而再将新开辟存储数组元素的空间清空。

基于以上的原因,Swift 5.9 推出了 consume 关键字,使用该关键字可以避免上述代码的性能损耗。

consume 的使用

对于上述代码,修改 doStuffUniquely() 函数调用这一行即可:

scss 复制代码
doStuffUniquely(with: consume x)

在传递的参数前面添加一个 consume 关键字修饰,这样就等于告诉编译器,x 变量存储的数据所有权,请转交给 doStuffUniquely() 函数的参数。需要注意的是,如果这样写之后,我们在 test() 函数中的后续代码就不可以再对 x 的数据进行修改了,因为我们已经明确的将 x 的数据所有权已经交了出去。

如果,后续再对 x 进行修改的话编译器会报错:

与 let 搭配使用

对于常量来说,也可以通过使用 consume 来进行生命周期的终结。当常量使用 consume 之后,常量就不可用了,因为它的值所有权已被交出,且它不可重新被赋值。

需要说明的是, consume 是对绑定的操作,而不是对值进行操作,所以如果将 x 赋值给另一个常量 other,当 x consume 之后,x 已不能使用,而 other 是不受影响的:

scss 复制代码
func useX(_ x: Int) -> () {}

func f() {
  let x = 10
  useX(x)
  let other = x
  _ = consume x
  useX(other)
}

_ = consume x 执行完之后, x 的生命周期已结束。而 other 是可以正常使用的,所以 useX(other) 并没有什么问题。

与 var 搭配使用

与 var 搭配使用则与 let 使用略有不同,当 consume 修饰的变量重新赋值之后,是可以正常使用的:

ini 复制代码
struct User {
    var name: String
}
    
func test() {
    var user = User(name: "jack")
    _ = consume user
    
//  user.name = "" // 编译报错
    user = User(name: "rose")
    print(user.name)
}

上面的代码我们可以看到,如果在 user consume 之后,直接对 user 进行 name 的赋值是不行的,原因就是 user 的数据所有权已经没了。

而对 user 进行重新赋值则是没问题的,后续也可以正常使用。

相关推荐
Keya21 小时前
lipo 命令行指南
ios·xcode·swift
zhangmeng21 小时前
SwiftUI中如何实现子视图向父视图传递数据?
ios·swiftui·swift
Saafo21 小时前
迁移至 Swift Actors
ios·swift
杂雾无尘2 天前
告别构建错误, iOS 开发架构难题全面解析, 避免 CPU 架构陷阱
ios·swift·客户端
大熊猫侯佩3 天前
探秘 WWDC 25 全新 #Playground 宏:提升 Swift 开发效率的超级神器
xcode·swift·wwdc
移动端小伙伴3 天前
10.推送的扩展能力 — 打造安全的通知体验
swift
移动端小伙伴3 天前
推送的扩展能力 — 打造个性化的通知体验
swift
移动端小伙伴3 天前
远程推送(Remote Push Notification)
swift
移动端小伙伴3 天前
本地通知的精准控制三角:时间、位置、情境
swift
移动端小伙伴3 天前
本地通知内容深度解析 — 打造丰富的通知体验
swift