1. ホーム
  2. swift

[解決済み] Swift の @escaping と Completion ハンドラ

2022-10-31 15:51:10

質問

Swiftの'Closure'をより正確に理解しようとしています。

しかし @escapingCompletion Handler は難解すぎる

Swiftの投稿や公文書をたくさん探しましたが、まだ足りないと感じました。

公式ドキュメントのコード例です。

var completionHandlers: [()->Void] = []

func someFunctionWithEscapingClosure(completionHandler: @escaping ()->Void){
    completionHandlers.append(completionHandler)
}

func someFunctionWithNoneescapingClosure(closure: ()->Void){
    closure()
}

class SomeClass{
    var x:Int = 10
    func doSomething(){
        someFunctionWithEscapingClosure {
            self.x = 100
            //not excute yet
        }
        someFunctionWithNoneescapingClosure {
            x = 200
        }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)

completionHandlers.first?() 
print(instance.x)

を使用する方法と理由は2つあると聞きました。 @escaping

1つはクロージャを格納するため、もう1つは非同期操作のためです。

以下は私の質問です。 :

まず、もし doSomething が実行されたら someFunctionWithEscapingClosure が実行され、そのクロージャはグローバル変数の配列に保存されます。

クロージャは{self.x = 100}だと思います。

どのように self で、グローバル変数に保存された{self.x = 100}で completionHandlers に接続することができます。 instance のオブジェクトは SomeClass ?

第二に、私は someFunctionWithEscapingClosure をこのように理解します。

ローカル変数のクロージャを格納するために completionHandler をグローバル変数completionHandlersに格納する。 we using キーワードをエスケープしてください。

を使わずに @escaping キーワード someFunctionWithEscapingClosure が返す、ローカル変数 completionHandler はメモリから削除されます。

@escaping はそのクロージャをメモリに保持します。

これで良いのでしょうか?

最後に、この文法が存在すること自体が不思議なんです。

これは非常に初歩的な質問かもしれませんが。

ある関数を特定の関数の後に実行させたい場合。特定の関数呼び出しの後に、ある関数を呼び出せばいいのでは?

上記のパターンを使用することと、エスケープコールバック関数を使用することの違いは何ですか?

どのように解決するのですか?

Swiftの完了ハンドラのエスケープと非エスケープ。

Bob Leeがブログの記事で説明しているように Bobと一緒にSwiftで完了ハンドラ :

ユーザーがアプリを使用中に更新していると仮定します。その際 更新が完了したら、ユーザーに通知したいですよね。おそらく、「おめでとうございます。 おめでとうございます。

では、ダウンロードが完了した後にのみ、コードのブロックを実行するにはどうしたらよいでしょうか。 では、ダウンロードが完了した後にのみ、コードのブロックを実行するにはどうすればよいのでしょうか。さらに、あるオブジェクトをアニメーションさせるのに、ビュー コントローラーが次に移動した後、どのようにすればよいのでしょうか。 ビューコントローラを次のビューに移動した後に、特定のオブジェクトをアニメーション化するにはどうしたらよいでしょうか?さて、私たちは を設計する方法について説明します。

私の豊富な語彙リストによれば、完了ハンドラは以下のものを表します。

物事が完了したときに何かをする

Bobの投稿は、完了ハンドラについて明確にしてくれます(開発者の観点からすると、我々が理解する必要があることを正確に定義してくれています)。

クロージャをエスケープする。

関数の引数でクロージャを渡すと、関数本体が実行された後にそれを使ってコンパイラに返します。関数が終了したとき、渡されたクロージャのスコープは、クロージャが実行されるまで、メモリ上に存在し、存在します。

関数を含むクロージャをエスケープするにはいくつかの方法があります。

  • ストレージ。グローバル変数、プロパティ、または呼び出し関数の過去のメモリに存在する他のストレージにクロージャを格納する必要がある場合、実行され、コンパイラを返します。

  • 非同期実行。デスパッチキューで非同期にクロージャを実行する場合、キューはメモリ内にクロージャを保持し、将来的に利用することができます。この場合、クロージャがいつ実行されるかはわかりません。

これらのシナリオでクロージャを使おうとすると、Swiftコンパイラはエラーを表示します。

このトピックについてより明確にするために、以下のサイトを参照してください。 この投稿はMediumにあります。 .

もう一つ、すべてのios開発者が理解する必要がある点を追加します。

  1. クロージャのエスケープ : エスケープクロージャとは、渡された関数が戻った後に呼び出されるクロージャのことです。言い換えれば は渡された関数より長生きする。
  2. エスケープしないクロージャ : 渡された関数内で呼び出されるクロージャ、つまり、関数が戻る前に呼び出されるクロージャです。