エスケ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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 参照による値のキャプチャ
- エスケapingクロージャ
- キャプチャリストとweak self
- オートクロージャ