LoginSignup
0
2

More than 1 year has passed since last update.

【Swift】クロージャについて整理してみた

Last updated at Posted at 2021-07-24

はじめに

クロージャについての理解がまだまだ浅く、なんとなくの理解となっているため、
私の頭の中を整理する意味でまとめていきます。

クロージャについて

そもそもクロージャとはなにか? についてSwift実践入門より以下を引用させていただきます。

クロージャは、再利用可能なひとまとまりの処理です。

クロージャにはクロージャ式という定義方法があります。
クロージャ式は名前が不要であったり、型推論によって型の記述が省略可能であったりと、関数よりも手軽に定義できます。

基本構文

クロージャは{ }を使用して、以下のフォーマットで記述します。

{ (引数名1:型,引数名2:型....) -> 戻り値の型 in
    //実行時の処理
    return 返却値
}

上記に従い実際に記述すると以下のようになります。

let equal = { (val1:Int,val2:Int) -> Bool in
    //実行時の処理
    return val1 == val2
}

(val1:Int,val2:Int)でInt型の値を2つ受け取り、Bool型の値を返します。
上記で実際に返却される値はval1とval2を比較したBool型の結果です。
これを変数equalに代入しています。

クロージャの呼び出し

クロージャを呼び出す際は、クロージャが代入されている変数名の後ろに( )をつけて、( )の中に受け渡す値を記述します。

let equal = { (val1:Int,val2:Int) -> Bool in
    //実行時の処理
    return val1 == val2
}
//呼び出し
equal(10,20)//false
equal(20,20)//true

糖衣構文(シンタックスシュガー)

クロージャを呼び出す際の値や変数宣言によって、型を自動的に推論できる場合は 、クロージャの引数の型を省略出来ます。
また、処理が単文の場合はreturnも省略可能です。

//変数宣言
let equal :(Int,Int) -> Bool

//クロージャを代入
equal = { (val1,val2) in
    //実行時の処理
    val1 == val2
}
//呼び出し
equal(10,20)//false
equal(20,20)//true


引数が無く、戻り値も無いクロージャは以下のように ( ) -> Void in と記述出来ます。

let closure = { () -> Void in
    print("Hello")
}
//呼び出し
closure()//Hello

さらに、( ) -> Void in も省略出来ます。

let closure = {
    print("Hello")
}
//呼び出し
closure()//Hello

クロージャのスコープ

//変数宣言
var closure :() -> Void

do{
    var count = 0
    closure = {
        count = count + 1
        print(count)
    }
}

//呼び出し
closure()//1
closure()//2
//print(count) //doのスコープ外からはcountにアクセスできないためコンパイルエラー

クロージャのスコープについて見ていきましょう。
do文の{}の中で宣言された変数countは、do文の{}の中のみが影響範囲となっており、本来、do文の外からのアクセスは出来ません。

しかし、クロージャは自身が定義されたスコープの変数への参照を保持しているため、do文の外からクロージャを通してcountの値を変更することが出来ます。この機能をキャプチャといいます。

トレイリングクロージャ

トレイリングクロージャとは関数の引数の最後にクロージャを渡した場合にクロージャを( )の外側に記述することができる方法です。
これにより、可読性が向上します。

func greeting(name:String,handler:(String) -> Void){
    handler(name)
}

//トレイリングクロージャあり
greeting(name: "ポチ") { val in
    print("\(val)さんこんにちは")
}
//トレイリングクロージャなし
greeting(name:"ポチ",handler:{ val in
    print("\(val)さんこんにちは")
})

//実行結果
//ポチさんこんにちは
//ポチさんこんにちは

参考

【Swift】クロージャ(基本編)
Swift実践入門

0
2
0

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