Swift

【Swift入門】クロージャの使い方をわかりやすく徹底解説!〜初心者でもわかるように解説します。〜

カズキ

今回はSwiftの機能の1つでもあるクロージャについて

初学者にも分かりやすいように解説していきたいと思います。

この記事を読むと、

・クロージャとは

・クロージャの実装方法

・クロージャと関数の違い

などを学ぶ事ができます。

ぜひ最後まで読んでいってください。

クロージャとは

Swiftでは、クロージャと呼ばれる記述を使用することで、コードを短く、スマートに記述することができます。クロージャは、関数のようなもので、関数と同じように実行できます。しかし、クロージャは、関数とは異なり、そのスコープ内で定義された変数を参照し続けることができます。

クロージャの記述方法は、以下のようになります。

{ (parameters) -> return type in
    statements
}

クロージャには、引数と戻り値がある場合もあり、ない場合もあります。引数と戻り値がある場合、それらを記述します。

クロージャは、主に以下のような用途で使用されます。

  • 関数やメソッドの引数として渡すことで、その中で実行される処理をカスタマイズすることができます。
  • 関数やメソッドの戻り値として返すことで、その中で実行される処理の結果を受け取ることができます。
  • 関数やメソッドの中で定義することで、その中で実行される処理を簡略化することができます。

クロージャは、非常に便利な機能のため、Swiftでの開発において頻繁に使用されます。

クロージャの具体例

Swiftでは、関数やメソッドの引数としてクロージャを渡すことができます。例えば、配列の中身を並び替えるsort()メソッドは、並べ替える順番を指定するためにクロージャを受け取ることができます。

以下は、配列の中身を昇順に並び替える例です。

let numbers = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
let sortedNumbers = numbers.sorted(by: { (a: Int, b: Int) -> Bool in
    return a < b
})

また、クロージャには、引数名や戻り値の型推論があるため、上記の例を書き換えることができます。

let sortedNumbers = numbers.sorted(by: { a, b in return a < b })

さらに短くすることもできます。

let sortedNumbers = numbers.sorted(by: { $0 < $1 })

このように、クロージャを使用することで、短く、スマートにコードを書くことができます。

また、クロージャは、変数や定数に代入し、別の場所でも使用することができます。

let multiplyClosure: (Int, Int) -> Int = { $0 * $1 }
let result = multiplyClosure(3,5)  //15

これらの例が、クロージャの使い方を示しているので、参考にしてみてください。

クロージャと関数の違い

Swiftでは、クロージャと関数の両方が使用できます。しかし、クロージャと関数は、それぞれ独自の特徴を持っています。

  • 関数: 関数は、特定の処理を行うために定義された、名前を持つブロックです。関数は、一度定義したら、それを複数回呼び出すことができます。
  • クロージャ: クロージャは、関数のようなもので、関数と同じように実行できます。しかし、クロージャは、関数とは異なり、そのスコープ内で定義された変数を参照し続けることができます。クロージャは、変数や定数に代入し、別の場所でも使用することができます。

また、関数は、通常、関数名を持ち、呼び出し可能なものであり、クロージャは、関数のようなもので、変数に代入し、別の場所でも使用することができます。

関数は、大量のデータ処理や、複雑な処理を行う場合に適しています。一方、クロージャは、短いスニペットのコードや、関数やメソッドの引数に渡したり、返すことで、柔軟なコードを書くことができます。

クロージャのキャプチャについて

Swiftのクロージャは、定義されたスコープ内で定義された変数を参照し続けることができます。これを、クロージャがスコープ外の変数を「キャプチャ」すると言います。

クロージャがスコープ外の変数を参照し続けるため、クロージャが定義された状態を「記憶」することができます。 そのため、クロージャは、スコープ外の変数の値を「キャプチャ」し、その後に実行されるタイミングでその値を使用することができます。

例えば、以下のようにクロージャが定義された場合、クロージャは、外側のスコープのx変数をキャプチャします。

var x = 0
let closure = { print(x) }
x = 1
closure() // 1

このように、クロージャは定義された時点の変数を記憶し、実行された時にその変数を使用することができる。

キャプチャには、スコープ外の変数を参照し続けるため、メモリリークや不要な処理が発生する可能性があるため、適切に管理する必要があります。

また、クロージャは、定義時に変数を「逃がす」こともでき、それを「弱参照」にすることで、メモリリークを防ぐことができます。

【応用編】クロージャを関数の引数に使う方法

Swiftでは、関数やメソッドの引数にクロージャを渡すことができます。これにより、関数やメソッドの中で実行される処理をカスタマイズすることができます。

例えば、以下のように、 performOperation 関数を定義し、その引数にクロージャを渡すことができます。

func performOperation(operations: (Int) -> Int, number: Int) -> Int {
    return operations(number)
}

この関数は、引数として受け取ったクロージャを実行し、その結果を返します。

そして、この関数を呼び出す時に、クロージャを引数に渡します。

let result = performOperation(operations: { number in 
    return number * number
}, number: 5) // 25

このように、関数やメソッドの引数にクロージャを渡すことで、関数やメソッドの中で実行される処理をカスタマイズすることができます。

また、クロージャを引数に渡すことで、関数やメソッドの呼び出し元で処理を定義することができるので、関数やメソッドを再利用することができます。

クロージャを引数に渡すことで、関数やメソッドをより柔軟に、かつカスタマイズ性を高めることができるため、非常に便利な機能です。

まとめ

ここではクロージャについて、

・クロージャとは
・クロージャの具体例
・クロージャと関数の違い
・クロージャのキャプチャについて
・【応用編】クロージャを関数の引数に使う方法

などについて解説しました。

クロージャは簡単にまとまった処理を記述するための関数のような処理で、意図した処理を明確、簡潔に書くために使用します。

皆さんの理解に少しでも役立てたら嬉しいです。

他にもSwiftの記事を書いてるのでよかったら読んでみてください。

また、1人での勉強に限界を感じたらiOSに特化したプログラミングスクール「iOSアカデミア」も検討してみてください!無料相談可能「最短・最速」でiOSエンジニアになれるように手助けしてくれます。