iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

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.

参照: https://github.com/apple/swift-evolution/blob/master/proposals/0286-forward-scan-trailing-closures.md#introduction

以前の記事で紹介した 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 で特定の関数がうまく動作しないという問題がありました。

github.com

参考

github.com

swift.org

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com