Swift5.3 つまみ食い【SE-0286編】
SE-0286 - Forward-scan matching for trailing closures
SE-0279 "Multiple Trailing Closures" threaded the needle between getting the syntax we wanted for multiple trailing closures without breaking source compatibility. One aspect of that compromise was to extend (rather than replace) the existing rule for matching a trailing closure to a parameter by scanning backward from the end of the parameter list.
以前の記事で紹介した Multiple Trailing Closures のソース互換性を保つために、複数の Trailing Closure がある場合の Closure マッチングに修正がはいったようです。
問題だった点
UIView のメソッドである animate
のように複数のクロージャーがあり、:animation
のみ使用するために Trailing Closure を使用すると、:animation
が使用されず末尾の :completion
が参照されてしまうという問題がありました。
class func animate( withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil ) UIView.animate(withDuration: 0.3) { self.view.alpha = 0 } // error: missing argument for parameter 'animations' in call animate(withDuration: 0.3) {
解決
これらが Swift5.3 からは、複数のクロージャで Trailing Closure を使用する場合は、先頭から順に Closure のマッチングが行われるようになったそうです。
UIView.animate(withDuration: 0.3) { self.view.alpha = 0 } // equivalent to UIView.animate(withDuration: 0.3, animations: { self.view.alpha = 0 })
正直これに関しては、特に既存のコードを Swift5.3 に乗り換えた場合、意図しないクロージャの参照によりソースブレイクする可能性があるため、Closure を省略するような時にはラベルをつけるのが個人的には無難な気がしました🤧
確か Nimble なんかもこの変更による影響で、Swift5.3 で特定の関数がうまく動作しないという問題がありました。