クロージャを関数や別のクロージャの引数として利用する場合にのみ有効な仕様として、属性とトレイリングクローリングがあります。
属性はクロージャの型の前に@属性名を追加して指定します。
func 関数名(引数名: @属性名 クロージャの型名) {
関数呼び出し時に実行される文
}
escaping属性
escaping属性は、関数に引数として渡されたクロージャが、関数のスコープ外で保持される可能性があることを示します。
コンパイラはescaping属性の有無によって、クロージャがキャプチャを行う必要があるかを判別します。
var queue = [() -> Void]()
func enqueue(operation: @escaping () -> Void) {
queue.append(operation)
}
enqueue {
print("executed")
}
enqueue {
print("executed")
}
queue.forEach{ $0() }
上のプログラムでは、引数のクロージャは、関数のスコープ外で、保持されます。
なので、escaping属性を指定していないとエラーになります。
autoclosure属性
引数をクロージャで包むことで、遅延評価を実現するための属性です。
func or(_ lhs: Bool, _ rhs: @autoclosure () -> Bool) -> Bool {
if lhs {
print("true")
return true
} else {
let rhs = rhs()
print(rhs)
return rhs
}
}
func lhs() -> Bool {
print("lhs関数が実行されました")
return true
}
func rhs() -> Bool {
print("rhs関数が実行されました")
return false
}
or(lhs(), rhs())
参考
[増補改訂第3版]Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plusシリーズ)