スコープ関数
スコープ関数とは、関数を引数に取ることで、関数のスコープを変えることができる関数です。
Kotlinの標準ライブラリにある apply
let
run
with
also
が当てはまります。
これを使うことで、1つのオブジェクトに対してたくさんの処理をしたいときに簡潔に記述できるようになります。
スコープ関数の使い方については以下の記事を参考にしてください。
Swiftにはスコープ関数はない
今までKotlinをやってきて、今まさにSwiftをやっているのですが、Kotlinの let
also
を使えなくて、不便だと感じることがありました。
なので、SwiftのClosureを使って、let
also
と使えるようにしました。
ソースコード
import Foundation
// ------------------ let ------------------
protocol LetProtocol {}
extension LetProtocol {
func `let`(_ closure: (Self) -> Void) {
closure(self)
}
}
extension NSObject: LetProtocol {}
// ------------------ also ------------------
protocol AlsoProtocol {}
extension AlsoProtocol {
func also(_ closure: (Self) -> Void) -> Self {
closure(self)
return self
}
}
extension NSObject: ApplyProtocol {}
let
は、自身を引数として受け取った関数を実行します。
Kotlinの let
と若干違う点は、Kotlinのほうでは関数を実行後に任意の型を返しており、返り値を設定してない場合は返り値がUnitが返っている点です。
also
は、自身を引数として受け取った関数を実行しているところまでは let
と同じで、異なるところは自身を返しているところです。
letの使用例
UserDefaultsに値を保存するとき
// ------------------ Before ------------------
UserDefaults.standard.set("aaaaaaa", forKey: "key1")
UserDefaults.standard.set("bbbbbbb", forKey: "key2")
// ------------------ After ------------------
UserDefaults.standard.let { it in
// UserDefaultsのスコープ
it.set("aaaaaa", forKey: "key1")
it.set("bbbbbb", forKey: "key2")
}
alsoの使用例
コードでUILabelを作るとき
// ------------------ Before ------------------
let helloLabel = UILabel()
helloLabel.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
helloLabel.text = "Hello"
helloLabel.textColor = UIColor.red
// ------------------ After ------------------
let helloLabel = UILabel().also { it in
// UILabelのスコープ
it.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
it.text = "Hello"
it.textColor = UIColor.red
}
このUILabelをViewに追加するとき、わざわざhelloLabel
のnamespaceを設定することなく、書くことができるようになります。
addSubview(UILabel().also { it in
it.frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0)
it.text = "Hello"
it.textColor = UIColor.red
})
スコープ関数を使ったメリット
- スコープを絞ることができた
- 1つのオブジェクトに対する処理{}内でまとめられた
- コードがすっきりした
- namespaceを省略して書くこともできる