SketchK's Studio.

Swift Tips 018 - Using self-executing closures for lazy properties

字数统计: 558阅读时长: 2 min
2019/10/01 Share

每天了解一点不一样的 Swift 小知识

代码截图

01.png

代码出处: Swift Tips 018 by John Sundell

小笔记

这段代码在说什么

代码截图里的核心点是在于 StoreViewController 里的 collectionView 属性不仅是一个延时加载存储属性,还采用了闭包的方式初始化属性缺省值。

lazy 关键字

延时加载属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用 lazy 来标识一个延时加载属性。

必须将延时加载属性声明成变量(使用 var 关键字),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延时加载。

用闭包的方式初始化属性缺省值

和其他属性一样,我们可以用自执行(self-executing)闭包来给 lazy 变量设定默认值,也就是用 = { /* some code */ }() 的方式替换掉 = some code 的方式。

需要注意的一点是,当属性是 lazy 时, 这意味着它的初始值暂时不会被计算,当需要计算的时候,self 已经完成初始化。这就是为什么你可以在那里使用 self ,这和非 lazy 属性正好相反:它的初始值在初始化阶段就被计算出来了。

这样做的好处

在说好处之前,我们先将代码还原成不用 lazy 关键字和自执行闭包的状态。你的代码大体可能如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class StoreViewController: UIViewController {
private var collectionView: UICollectionView?

override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
self.collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)
self.collectionView.delegate = self
self.collectionView.dataSource = self
if let subView = self.collectionView {
view.addSubview(subView)
}
}
}

相比于原先的代码,viewDidLoad 里面的核心逻辑是向 view 里添加 子视图。但现在的这份代码在 viewDidLoad 整合了 collectionView 的初始化代码,除了代码结构上变得有些不那么整洁外,我们也可能无法保证 collectionView 只被初始化一次了。

所以用自执行闭包初始化 lazy 属性的方式,你觉得如何?

CATALOG
  1. 1. 代码截图
  2. 2. 小笔记
    1. 2.1. 这段代码在说什么
    2. 2.2. lazy 关键字
    3. 2.3. 用闭包的方式初始化属性缺省值
    4. 2.4. 这样做的好处