0Pricing
Swift Academy · レッスン

エスケapingクロージャ

関数の終了後も存続するクロージャを保存します。

「エスケapingクロージャ」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

エスケープするクロージャーとエスケープしないクロージャー

デフォルトでは、クロージャーの引数はエスケープしません。関数が戻る前に呼び出す必要があります。後で保存して呼び出す可能性がある場合は、@escapingを付けます。

エスケープしないクロージャー

このクロージャーは同期的に実行され、関数が戻ると破棄されます:

func run(_ work: () -> Void) {
    work()
}
run { print("done now") }  // "done now"

@escaping が必要な理由

後で使うためにクロージャーを保存するには、@escapingが必要です:

var handlers: [() -> Void] = []
func register(_ handler: @escaping () -> Void) {
    handlers.append(handler)  // escapes the function
}
register { print("later") }
handlers[0]()  // "later"

非同期処理でエスケープするクロージャー

完了ハンドラーは、関数が戻った後に実行されるためエスケープします:

func load(then completion: @escaping (String) -> Void) {
    // imagine async work
    completion("data")
}
load { result in print(result) }  // "data"

self は明示的に記述する必要があります

エスケープするクロージャーの中でインスタンスメンバーにアクセスするときは、self.を明示的に記述する必要があります — これは、クロージャーがselfを保持する可能性があることを示すためです。

エスケープするクロージャーで self を明示する

コンパイラーは明示的な参照を要求します:

class Loader {
    var name = "L"
    func start(_ done: @escaping () -> Void) {
        let cb = { print(self.name); done() }
        cb()
    }
}
Loader().start { print("finished") }  // "L" then "finished"

複数のコールバックを保存する

エスケープするクロージャーを使うと、オブザーバーのリストを構築できます:

class Emitter {
    private var listeners: [(Int) -> Void] = []
    func on(_ l: @escaping (Int) -> Void) { listeners.append(l) }
    func fire(_ v: Int) { listeners.forEach { $0(v) } }
}
let e = Emitter()
e.on { print("got \($0)") }
e.fire(7)  // "got 7"

保存したクロージャーを返す

プロパティに保持されるクロージャーはエスケープします:

class Button {
    var action: (() -> Void)?
    func setAction(_ a: @escaping () -> Void) { action = a }
}
let b = Button()
b.setAction { print("tapped") }
b.action?()  // "tapped"

オプショナルのクロージャーはエスケープします

オプショナルのクロージャー引数は暗黙的にエスケープします(Optionalでラップされるため)。そのため保存できます:

func maybe(_ f: (() -> Void)?) {
    f?()
}
maybe { print("ran") }  // "ran"

タスクの配列にエスケープする

後回しにした処理のキューは、エスケープの典型的な用途です — 各クロージャーを保存し、後で実行します:

var tasks: [() -> Int] = []
func schedule(_ task: @escaping () -> Int) {
    tasks.append(task)
}
schedule { 1 + 1 }
schedule { 10 * 2 }
print(tasks.map { $0() })  // [2, 20]

パフォーマンスに関する注意

エスケープしないクロージャーは、より積極的に最適化できます(ヒープのメモリ確保が不要なためです)。可能な限りクロージャーはエスケープさせず、本当に保存または遅延する必要がある場合だけエスケープさせてください。

func sum(_ xs: [Int], _ f: (Int) -> Int) -> Int {
    xs.reduce(0) { $0 + f($1) }   // non-escaping, fast
}
print(sum([1, 2, 3]) { $0 * $0 })  // 14

クイックチェック

クロージャーの引数に@escapingを付ける必要があるのは、どのような場合ですか?

まとめ

エスケープするクロージャーについて学びました:

  • エスケープしないクロージャーがデフォルトであり、関数が戻る前に実行されます
  • クロージャーを保存または後で実行するには、@escapingが必要です
  • エスケープするクロージャーでは、self.へのアクセスを明示する必要があります
  • オプショナルのクロージャー引数は暗黙的にエスケープします。速度のためには、エスケープしないクロージャーを優先してください

次は、キャプチャリストと weak self です。

よくある質問

「エスケapingクロージャ」レッスンは無料ですか?

はい。「エスケapingクロージャ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「エスケapingクロージャ」で何を学びますか?

関数の終了後も存続するクロージャを保存します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「エスケapingクロージャ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 参照による値のキャプチャ
  2. エスケapingクロージャ
  3. キャプチャリストとweak self
  4. オートクロージャ
← Swift Academyに戻る