2019/07/09 追記
※ @nukka123 さんのコメントより、Swiftのlazyプロパティという仕様どんな処理を呼ぼうが異なるスレッドからアクセスすれば初期化処理が1回に止まる保証はないことが判明してます。
実行環境
Xcode 10.2.1
Swift 5
例
ViewController.swift
class ViewController: UIViewController {
private lazy var label: UILabel = {
return ViewController.createLabel()
}()
init() {
super.init(nibName: nil, bundle: nil)
self.addSubview(label)
}
func setup(text: String) {
label.text = text
}
static func createLabel() {
let label = UILabel()
return label
}
}
init()
で初回のアクセスをしたタイミングでlabelプロパティが生成され、2回目以降にsetup(text:)
メソッドでアクセスした際には生成済みのインスタンスにアクセスされることを想定していた。
が、ViewController.createLabel()
が2回目以降も走っていることが発覚。
解決策
lazyプロパティ内の定義をいずれかに変更
要は、staticメソッドさえ使わなければ想定通りの遅延初期化プロパティな挙動をする。
直接生成
private lazy var label: UILabel = {
let label = UILabel()
return label
}()
インスタンスメソッドを用いて生成
private lazy var label: UILabel = {
return self.createLabel()
}()
static func createLabel() {
let label = UILabel()
return label
}
lazyではなくlet宣言にする
private let label: UILabel
init() {
self.label = ViewController.createLabel()
super.init(nibName: nil, bundle: nil)
self.addSubview(label)
}
static func createLabel() {
let label = UILabel()
return label
}