Help us understand the problem. What is going on with this article?

lazyプロパティ内でstaticメソッドを使用すると、2回目以降のアクセスでも処理が走る場合がある

More than 1 year has passed since last update.

2019/07/09 追記

@nukka123 さんのコメントより、Swiftのlazyプロパティという仕様どんな処理を呼ぼうが異なるスレッドからアクセスすれば初期化処理が1回に止まる保証はないことが判明してます。

https://qiita.com/m-yamada1992/items/d77adc52b75f6d44c3f6#comment-f24b8fc4241d8b918ce3

実行環境

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
    }
m-yamada1992
現在、スマートフォンアプリの開発業務を中心に担当。 興味はいろいろ。
studyplus
学習管理アプリ「Studyplus」を開発・運営する会社です
https://info.studyplus.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away