Swift

デフォルト引数で他の引数の値を使う時のワークアラウンド

デフォルト引数を使ってnilを安全な値にフォールバックさせるメソッドを書くこともあると思います。次のようなメソッドです。

func of(size: CGFloat, defaultFont: UIFont) -> UIFont {
   return UIFont(name:"deprecatable font", size: size)
}

これは、UIFontを生成し返すメソッドです。
UIFontのname指定は将来的なiOSのアップデートで内臓フォントが消された場合にnilになる可能性があります。(ここでは本題じゃないのでそういうことにしてください)

ここで、defaultFontを毎回指定するのは大変なのでデフォルトの値をいれておこうという話になると問題になります。

func of(size: CGFloat, defaultFont: UIFont = UIFont.systemFont(ofSize: size)) -> UIFont {
  return UIFont(name:"deprecatable font", size: size) ?? defaultFont
}

これは

Use of unresolved identifier 'size'

と怒られます。sizeはデフォルト引数からは参照できないからです。

一般的なワークアラウンドとしてnilを入れるという方法があります。

func of(size: CGFloat, defaultFont: UIFont? = nil) -> UIFont {
  return UIFont(name:"deprecatable font", size: size) ?? defaultFont ?? UIFont.systemFont(ofSize: size)
}

これで正常に動作しますが、本来必要なdefault引数にnilが指定できるのは混乱の元です。

そこで、クロージャを使うと便利に引数を扱うことができます。

typealias FontFactory = (_ size: CGFloat) -> UIFont
func of(size: CGFloat, defaultFont factory: FontFactory) -> UIFont {
  return UIFont(name:"deprecatable font", size: size) ?? factory(size)
}

(ここまでやるならデフォルトフォントのenumも欲しいので、普通にFactoryクラス作ってもいいかもとか思った)