0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Swift] クロージャ(Closures)を理解してみよう

Last updated at Posted at 2020-06-06

クロージャについてまとめたものを共有します。
環境は以下の通りです
Swift 5.1
Xcode 11.3

クロージャの形態

{(パラメータリスト) → リターン型 in 実行するコード}
何もパラメーターで受け取らず、何も返さないクローザーは ( ) → ( ) です。

Swiftの関数はクロージャ!

Swiftの関数はクロージャです。
クロージャは「関数の本体内のスコープ内で外部変数への参照をキャプチャできること」を意味します。

例えば、下のドグのインスタンスを参照してみよう。
whatThisDogSaysを参照できるのが分かります。
スクリーンショット 2020-06-06 12.29.21.png

dothis関数にはDogインスタンスがないが参照により"arf"を呼び出します。
Dog 変数 d と関数 barkFunction の両方が、同じDogインスタンスへの参照を保持しているからです。
スクリーンショット 2020-06-06 12.29.36.png

クロージャがコードをどのように改善するか

作ったクロージャコードを簡略化にして、より便利に使うことができます。
スクリーンショット 2020-06-06 13.17.38.png
上の関数はイメージを作るtrailing closureです。

スクリーンショット 2020-06-06 13.20.35.png このような呼び出すことできるので便利です。
スクリーンショット 2020-06-06 13.21.21.png 繰り返されるコーディングが嫌ならこのように書き換えます。
スクリーンショット 2020-06-06 13.23.24.png ハードコーディングがいやならこのように修正するのもよいでしょう。
スクリーンショット 2020-06-06 13.25.24.png 上の関数はこのように呼び出すことができます。

関数をりタンする関数

上の例ではイメージをリターンするが、今回は関数をリターンしてみよう。
関数から値として返された関数を見たことがない方は息が詰まるかもしれないが、とりあえずゆっくりみてみよう。
スクリーンショット 2020-06-06 13.53.56.png
下線を引いた部分はリターンされる関数です。
関数をリターンするために fという関数を作りました。
fim でリターンされているイメージだけを持ってますし、それをリターンします。

スクリーンショット 2020-06-06 13.54.07.png 上の関数を変数に保存すると変数は関数の形になります(関数が関数をリターンするため)。 こうなると、普通の関数を呼び出すことができるので便利になります。 (`makeRoundedRectangle`関数はファクトリーのように使える) スクリーンショット 2020-06-06 17.48.28.png 上の関数はよりSwift化した形です。変数`im`は必要ないため省略し、関数名の前に`return`をつけます。
スクリーンショット 2020-06-06 17.51.27.png 上の関数をよりSwift化した形です。関数名`f`も必要ないです。
スクリーンショット 2020-06-06 17.51.51.png リターンされる関数前の`return`も省略可能です。

キャプチャされた変数を設定(set)します。

クロージャは変数を設定(set)できます。
スクリーンショット 2020-06-06 18.10.38.png

簡単な例です。

キャプチャした環境を保存するクロージャ

スクリーンショット 2020-06-06 18.54.10.png

ある関数は直接呼び出されるのではなく後で実行するため、その関数が保存される(その環境をとらえ、時間の経過とともに保存する)クロージャをescaping closureと言います。(上のように@escapingをつきます。)

スクリーンショット 2020-06-06 18.54.20.png

次のようなcountedGreet()を呼びだすとカウントされた値が出力されます。
一体どこで変数をカウントするでしょうか。
変数countはローカル関数(匿名関数)で宣言されてないですが、それを利用して0に初期化され、後にカウントしています。
もし、countが匿名関数内で宣言された場合、countedGreet()が呼び出されるたびに ctを0に設定します。
それは、countedGreet()が呼び出されるたびにインクリメントするように、ある親密的な環境にcountedGreet()が保持されるからです。

参考

iOS13 Programming Fundamentals with Swift, Matt Neuburg(2019) p50 - 58

0
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?