開発現場で役に立つSwiftのクロージャの使い方

クロージャとは自己完結型のメソッドのようなものです。より専門的な解説についてはWikiPediaなどでもされているので気になる方は確認してみると良いですが、定義についてはざっくりとした理解で問題ないかと思います。

重要なのは具体的な使い方を知ることです。このページでは、開発現場で役立つSwiftのクロージャの使い方について解説します。

クロージャの基本的な使い方

クロージャ―の基本的な構文は以下のようになります。

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

この構文にサンプルコードを当てはめると以下のようになります。

var cl = { () -> () in print("クロージャのテスト") }
//クロージャの実行
cl()

また引数と戻り値を省略して記述することも可能です。

var cl = { print("クロージャのテスト") }
cl()

型を指定して宣言する

クロージャでは引数と戻り値の型を指定して宣言することが可能です。以下がサンプルコードになります。

var cl : ((Int, Int) -> Void)

次に引数を指定してクロージャ内で処理を実行するサンプルコードです。

var cl : ((Int, Int) -> Void)
cl = { (num1: Int, num2: Int) -> Void in
print(num1 + num2)
}
cl(100, 200)

上記のサンプルコードを実行すると、300と出力されます。

クロージャを呼び出してそのままクロージャ内で処理が実行されました。今までの説明でクロージャのイメージがなんとなくぼやけていた方も、上記のサンプルコードでピンときたのではないでしょうか。

使い方はほぼメソッドと同じで、異なる点は戻り値があってもなくてもクロージャ内で処理が完結するということです。次に、戻り値がある場合のサンプルコードです。

var cl : ((Int, Int) -> Int)
cl = { (num1: Int, num2: Int) -> Int in
return num1 + num2
}
print(cl(100, 200));

この場合出力処理自体はクロージャを呼び出すところで行っています。クロージャ自体は引数で受け取った値を計算して返すようになっているため、使い方としてはメソッドとほぼ同じです。

クロージャの応用的な使い方

クロージャを引数にクロージャを実行する方法を紹介します。Int型の変数二つ、クロージャを引数にメソッドを実行するサンプルコードを紹介します。

func sampleFunc(num1:Int, num2:Int, cl:(Int,Int) -> Int){
print(cl(num1, num2))
}
sampleFunc(num1:100, num2:200, cl:{(num1:Int, num2:Int) -> Int in num1 + num2})

上記のサンプルコードを実行すると300と出力されます。メソッドには内容な書き方なので、他の言語の経験者でもパッと見わかりにくいかもしれません。

結局クロージャはどう使えば良いのか

以上 、クロージャの使い方を紹介してきましたが、結局どう使いこなせば良いのでしょう。Swift独自の概念であるがゆえに、どう使えば良いのか迷ってしまうのがクロージャです。基本的にはクロージャでできることはメソッドでもできるので、はっきり言ってしまえば必ずしもクロージャを使用する必要はありません。

クロージャを使用するメリットとしては、場合によってはコードが短く簡潔になる場合があるということです。たとえば、以下のサンプルコードはクロージャで記述した結果シンプルになっています。

let foods =["Orange", "Apple", "Banana", "Melon", "PainApple"]
func backward(s1: String, _ s2: String) -> Bool{
return s1 > s2
}
var foods_sort = foods.sorted(by: backward)
print(foods_sort)

上記のコードを実行すると、以下のようにコンソール出力されます。

[“PainApple”, “Orange”, “Melon”, “Banana”, “Apple”]

アルファベットの大きい順にソートするコードです。

関数とクロージャの比較

関数とクロージャの違いは上記の通りですが、わかりやすいように同じ内容の処理をそれぞれ関数とクロージャで実装してみます。

//関数
func simpleFunc() {
println("これは関数です。")
}
simpleFunc()

//クロージャ
var simpleClosure: () -> () = {
println("これはクロージャです。")
}
simpleClosure()

同じ単純出力処理です。

クロージャはvarで宣言していますが、引数も戻り値もないため上記の例だと関数でもクロージャでもほぼ同じです。次に戻り値のあるもので関数とクロージャの違いを検証してみます。

//String引数付関数
func paramFunc(param:String) -> String{
return "こんにちは。" + param + "さん"
}
println(paramFunc("もく"))

//String引数付クロージャ
var paramClosure: (String) -> String
//クロージャの実装
paramClosure = {
p -> String in
return "こんにちは。" + p + "さん"
}
println(paramClosure("もく"))

クロージャではparamをp一文字で表現しているためややコードがシンプルです。次に関数とクロージャの違いがより顕著に表れるサンプルコードを紹介します。

//Int引数付関数
func intParamFunc(p1:Int, p2:Int)->Int{
return p1 + p2
}
println(intParamFunc(2,6))

//Int引数付クロージャ
var intParamClosure: (Int,Int) -> Int
//クロージャの実装
intParamClosure = {
p1,p2 -> Int in
return p1 + p2
}
println(intParamClosure(3,5))

Int型で二つの引数を渡し、戻り値を返しています。特に引数が増えたときに関数とクロージャの差は現れやすく、記述的にはクロージャの方が引数とクロージャ名を分けて書く文見やすいのではないでしょうか。関数を使用していて、引数が多すぎて見にくくなった経験を持っている方は多いかと思います。クロージャの場合引数部分にカッコが付かないので見やすいです。

まとめ

以上、クロージャの基本的な使い方等について解説してきました。

関数との違いはあるものの、個人的にはそこまで大きな違いはないような感じもします。またSwift独自の概念でもあるので、使いにくいのであれば無理して使用する必要もないような印象です。

基本は関数で、頭の片隅にクロージャも置いておくくらいで良いかもしれません。クロージャをまったく知らないのは損ですが、なんでもかんでもクロージャにするとかえって非効率なので、関数をベースにクロージャを使用した方が利便性の高いシチュエーションでのみクロージャを使用するのが良いかと思います。

▼Swift関連の記事一覧
1, 【Swiftのフリーランス案件情報付き】仕事やエンジニアの将来性・学習方法!
2, 繰り返し処理に使えるSwiftのfor文とfor-in文の便利な使い方まとめ
3, 条件分岐に便利なSwiftのSwitch文の使い方まとめ
4, アプリ開発でよく使うSwiftの4つの文法を解説します
5, Swiftのoptional型を使いこなすための7つのポイント
6, Swiftで文字列を扱うためのstring型の使い方
7, Swiftでの配列の宣言・初期化・代入・参照の方法まとめ
8, 実際の開発現場でのSwiftの変数・定数の使われ方を解説します
9, Swiftでif let文を使って出来ることとguard letの使い分けに関して
10, 開発現場でよく使うSwiftのif文の条件分岐をまとめました
11, SwiftにおけるTupleの使い方とわかりやすく解説します
12, 初心者にオススメのSwiftのサンプルコードをまとめてみました
13, SwiftのString、Int、Doubleの型の変換方法をまとめました
14, (この記事)開発現場で役に立つSwiftのクロージャの使い方
15, Swiftでwhileを使って上手に繰り返し処理を行おう
16, Swiftで文字列の長さをチェックするのにlengthを使ってみよう
17, Swiftのdictionaryの使い方と初期化方法をまとめました
18, Swiftの値渡しと参照渡しに関するまとめ
19, Swiftで参照渡ししたい時のinoutの便利な使い方
20, Swiftでfor-in文でindexを使いたい時の方法まとめ
21, Swiftでのクラスとstruct(構造体)の使い分けを解説します

人気記事

編集部おすすめ記事

この記事を読んだ人はこんな記事を読んでいます