Swiftで1回だけ実行する5つの方法

Swiftの、1回だけ実行するイラスト Swift
この記事は約11分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればサンプルコードを活用して機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Swiftを学び始めると、特定の操作を一度だけ実行させたい場面に遭遇することがあります。

例えば、初回のみのセットアップ処理や、特定の条件下でのみ一度だけのAPI呼び出しなどが考えられます。

Swiftにはこのような「1回だけ実行」をサポートする多くの方法や機能が存在します。

この記事では、Swiftでの「1回だけ実行」の方法を5つ選び、初心者向けに詳細に解説します。

サンプルコードを交えながら、その実行結果や注意点も紹介します。

Swiftの経験が浅い方でも、この記事を読めば「1回だけ実行」の方法を簡単に理解・実装できるようになるでしょう。

●Swiftの1回だけ実行とは

Swiftの「1回だけ実行」とは、文字通りコードの特定の部分を一度だけ実行することを指します。

これは、アプリケーションの特定の部分でのみ実行が必要な場面や、複数回の実行を避けたい場面などで非常に役立ちます。

○1回だけ実行の必要性

1回だけ実行が必要となるシチュエーションは多岐にわたります。

例としては、アプリの初回起動時に表示するチュートリアル、ユーザーが特定の条件を満たした時にのみ表示する特典情報、一度だけの初期化処理やセットアップなどが挙げられます。

これらの処理を毎回実行すると、不要なリソースの消費やユーザーエクスペリエンスの低下が生じる恐れがあります。

そのため、特定の処理を1回だけ実行させることで、アプリの効率やユーザーエクスペリエンスの向上が期待できます。

○Swiftにおける1回だけ実行の背景

Swiftにおける「1回だけ実行」の機能や方法は、Swiftの言語設計やライブラリの設計に起因しています。

特に、Swiftは安全性を重視した言語設計がされており、それに伴い1回だけの実行も安全に、そして簡単に行えるようにサポートされています。

また、Swiftの標準ライブラリや外部ライブラリには、この「1回だけ実行」をサポートするための多くの機能やメソッドが提供されています。

●1回だけ実行する方法の基本

Swiftで関数やブロックを1回だけ実行させる方法は、プログラムの効率性やユーザーエクスペリエンスの向上に貢献します。

これを実現するためには、次のような方法があります。

○サンプルコード1:DispatchOnceを使用する方法

このコードではDispatchOnceを使って、関数を1回だけ実行するコードを表しています。

この例では、特定の処理を1回のみ実行しています。

// 1回だけ実行するためのtokenを定義
var onceToken: DispatchOnceToken = DispatchOnceToken()

// 1回だけ実行する関数
func executeOnlyOnce() {
    dispatch_once(&onceToken) {
        print("この関数は1回だけ実行されます。")
    }
}

executeOnlyOnce()
executeOnlyOnce()

上記のサンプルコードを実行すると、コンソールには「この関数は1回だけ実行されます。」というメッセージが1回だけ表示されます。

2回目のexecuteOnlyOnce()は実行されず、1回目のみが実行されるのが確認できるでしょう。

○サンプルコード2:Static変数を利用する方法

このコードではstatic変数を使って、関数を1回だけ実行するコードを表しています。

この例では、関数内部のstatic変数を使用して1回のみの実行を制御しています。

func executeUsingStatic() {
    static var hasExecuted = false

    if !hasExecuted {
        print("この関数も1回だけ実行されます。")
        hasExecuted = true
    }
}

executeUsingStatic()
executeUsingStatic()

このサンプルコードを実行すると、やはりコンソールには「この関数も1回だけ実行されます。」というメッセージが1回だけ表示されることが確認できます。

2回目のexecuteUsingStatic()呼び出しでは何も実行されないのが特徴です。

○サンプルコード3:lazyキーワードを活用する方法

このコードではlazyキーワードを利用して、変数の初期化を1回だけ行うコードを表しています。

この例では、lazyキーワードを使って変数の初期化を遅延させ、初めてアクセスされたときに1回だけ初期化を行っています。

class MyClass {
    lazy var onlyOnceVariable: String = {
        print("変数が初期化されます。")
        return "Initialized"
    }()
}

let myInstance = MyClass()
print(myInstance.onlyOnceVariable)
print(myInstance.onlyOnceVariable)

上記のサンプルコードを実行すると、「変数が初期化されます。」というメッセージが1回だけ表示されます。

onlyOnceVariableへのアクセス時にのみ初期化が行われるのが特徴です。

●1回だけ実行の応用例

Swiftでの1回だけ実行の機能は、実際のアプリケーション開発においても多くの応用が考えられます。

ここでは、具体的な応用例として2つのシーンを取り上げ、それぞれのシーンにおいて1回だけ実行する方法をサンプルコードとともに解説していきます。

○サンプルコード4:初回起動時にのみ実行するUI更新

アプリを初めて起動したときだけ、特定のUIを表示したい場合があります。

たとえば、チュートリアルの表示や特定のお知らせを一度だけ表示するような場合です。

下記のコードは、初回起動時にのみ特定のUIを表示する例です。

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let isFirstLaunch = UserDefaults.standard.bool(forKey: "isFirstLaunch")

        if !isFirstLaunch {
            updateUIForFirstLaunch()
            UserDefaults.standard.set(true, forKey: "isFirstLaunch")
        }
    }

    func updateUIForFirstLaunch() {
        // 初回起動時のUI更新ロジックを記述
        print("初回起動時のUIを更新")
    }
}

このコードでは、UserDefaultsを使って初回起動かどうかの情報を保存・取得しています。

isFirstLaunchというキーで初回起動情報を取得し、初回起動時であればupdateUIForFirstLaunch関数を実行してUIを更新します。

そして、初回起動の情報を保存して次回以降の起動時にはUI更新が行われないようにします。

この例では、初回起動時に"初回起動時のUIを更新"という文字列がコンソールに表示されることになります。

○サンプルコード5:API呼び出しを1回だけ行うロジック

APIを利用したアプリケーション開発において、特定のAPIを1回だけ呼び出したい場合があります。

下記のコードは、特定の条件下でAPIを1回だけ呼び出す例です。

import UIKit

class APIViewController: UIViewController {

    var isAPICalled = false

    override func viewDidLoad() {
        super.viewDidLoad()

        if !isAPICalled {
            callAPI()
            isAPICalled = true
        }
    }

    func callAPI() {
        // API呼び出しのロジックを記述
        print("APIを呼び出しました")
    }
}

このコードでは、isAPICalledというBool型の変数を利用してAPIの呼び出し状態を管理しています。

isAPICalledがfalseの場合、つまりAPIがまだ呼び出されていない場合にのみcallAPI関数を実行し、APIを呼び出します。

そして、APIを呼び出した後はisAPICalledをtrueに更新して、次回以降の呼び出しを防ぎます。

この例では、APIを1回だけ呼び出すロジックが実装され、"APIを呼び出しました"という文字列がコンソールに表示されることになります。

●注意点と対処法

Swiftでのプログラムを効率的に開発する際に、ある関数やブロックを1回だけ実行することが求められる場面があります。

しかし、そのような実装を行う上で注意すべき点や、問題が発生した場合の対処法についても知っておくことは非常に重要です。

○スレッドセーフな1回だけの実行

マルチスレッド環境下でのプログラミングを行う際、複数のスレッドが同時に同じコードにアクセスすることで予期しない動作やエラーが発生する可能性があります。

そのため、1回だけ実行するコードもスレッドセーフに実装する必要があります。

このコードでは、DispatchOnceを利用してスレッドセーフに1回だけ実行する方法を表しています。

DispatchOnceは、指定したクロージャを一度だけ実行するためのAPIで、マルチスレッド環境でも安全に利用できます。

var onceToken: DispatchOnce = DispatchOnce()

DispatchQueue.global().async {
    onceToken.perform {
        print("このクロージャは一度だけ実行されます")
    }
}

上記の例では、グローバルキューで非同期にクロージャを実行していますが、DispatchOnceを使用しているため、クロージャ内の処理は一度だけ実行されることが保証されます。

このようにして、複数のスレッドから同時にアクセスされる可能性がある場合でも、一度しか実行されないコードを安全に実装することができます。

○メモリリークの回避

Swiftでの開発を行う際、メモリリークは非常に注意すべき問題の一つです。

特に、クロージャ内で自身を参照すると、メモリリークが発生する可能性が高まります。

このコードでは、クロージャ内でselfを弱参照としてキャッチし、メモリリークを回避する方法を表しています。

class MyViewController: UIViewController {
    var completionHandler: (() -> Void)?

    func setup() {
        completionHandler = { [weak self] in
            guard let self = self else { return }
            self.updateUI()
        }
    }

    func updateUI() {
        // UIの更新処理
    }
}

上記の例では、MyViewControllerクラス内でcompletionHandlerクロージャを定義しています。

クロージャ内でselfを参照する場合、[weak self]という弱参照を用いることで、MyViewControllerインスタンスがメモリリークを起こさずに正しく解放されるようにします。

●カスタマイズ方法

Swiftにおける1回だけの実行のロジックは非常に便利ですが、時にはその方法をカスタマイズして、独自の要件に合わせる必要があります。

ここでは、Swiftで1回だけの実行ロジックをカスタマイズするためのテクニックを、詳細なサンプルコードと共に紹介します。

○独自の1回だけ実行ロジックの構築

独自の1回だけの実行ロジックを構築する場面として、特定の条件下でのみコードを実行したい場合が考えられます。

ここでは、指定された回数だけ実行するカスタマイズロジックの例を紹介します。

class ExecuteOnce {
    private var executed = false

    func execute(task: () -> Void, condition: () -> Bool) {
        if !executed && condition() {
            task()
            executed = true
        }
    }
}

let once = ExecuteOnce()
once.execute(task: {
    print("このタスクは一度だけ実行されます。")
}, condition: {
    return true // この条件を変更することで、実行の可否を制御できます。
})

このコードでは、ExecuteOnceクラスを使用してタスクを一度だけ実行します。

この例では、condition関数がtrueを返す場合のみ、task関数が実行されるようになっています。

condition関数の中身を変更することで、実行の可否を制御することができます。

まとめ

Swiftでの1回だけの実行は、アプリケーションの効率的な動作やユーザーエクスペリエンスの向上に非常に役立ちます。

この記事で紹介した5つの方法やカスタマイズのテクニックを駆使して、柔軟かつ効果的なプログラムの実装を行ってください。

Swiftの持つこのような機能を最大限に活用して、より高品質なアプリケーションを開発しましょう。