OKADA LABO

swift クロージャって結局なに?

swiftやってると必ずつまづくのが
クロージャって結局なんなの?って話です。

これは端的に説明するのは難しい。
結論から言うとただの記述方法なのですが、概念が広いので、
言葉だけで表現するのは難しいのです。

基本的概念を頭に置いときながら
利用の事象を追いつつ
「こういうものだ」と感じて
その事象に慣れるのが一番いいと思います。

クロージャには以下の側面があるので
迷ったら何度もここに立ち戻りましょう。

  • クロージャとは、文(コード)の中に直接埋め込むことのできる命令のかたまりである
  • 引数にコードのかたまりとして処理を指定できる
  • 関数に似た変数
  • {}の範囲がクロージャ

文章だけではよくわからないですので、以下の事象を見ながら何度も立ち戻ってください。
だんだん分かります。

クロージャの書き方

{ ( 引数名:型 ) -> 戻り値の型 in
  処理
}

です。よくわからんですね。
次の事象を見てみましょう。
簡単な関数の利用例です。

func calc(num1:Int, num2:Int) -> Int{
    return num1 + num2
}

let num = calc(num1: 1, num2: 2)
print(num)
=>3

このfunc calc の処理部分をクロージャで書くことができます。

{ ( 引数名:型 ) -> 戻り値の型 in
  処理
}

のルールで

{ (num1:Int, num2:Int) -> Int in
  return num1 + num2
}

と書けます。
これ
(num1:Int, num2:Int) -> Int{
return num1 + num2
}
と同じ意味になります。

また、クロージャ記述はそのまま変数に代入できます。

var calc = { (num1:Int, num2:Int) -> Int in
    return num1 + num2
}

calc(1, 2)
=>3

変数として存在しながら関数として振る舞うのです。
ちょっと分かってきたでしょ?

もっと単純に捉えると

func hoge(){
  print("ほげほげ")
}

これの処理部分だけ抜き出すと

(){ print("ほげほげ") }

これをクロージャで書き換える。型はないのでVoid。よって

{ () -> Void in
    print("ほげほげ")
}

になるんですね。
そしてクロージャでは引数、型がないなら省略できます。

{ print("ほげほげ") }

になるんですね。

このクロージャは引数として指定できます。
例えば、モーダルビューを表示するコード

self.present( controller, animated:true, completion:{print("ほげほげ")} )

ちょっとわかってきたでしょ?