🎨
[SwiftUI] クロージャスタイルのModifierでバージョン分岐を楽に書く
SwiftUIでアプリを開発していると、異なるiOSバージョンで異なるスタイルを適用したい場面によく遭遇します。しかし、#available を使ったバージョン分岐は時として冗長なコードを生み出してしまいます。
バージョン分岐による冗長なコード
理想的だが書けないコード
まず、理想的には以下のような書き方ができれば良いのですが、これはSwiftUIの仕様上不可能です。
Button()
if #available(iOS 26.0, *) {
.buttonStyle(.glassProminent)
} else {
.buttonStyle(.borderedProminent)
}
現実的だが冗長なコード
実際には、以下のような書き方をする必要があります。
if #available(iOS 26.0, *) {
Button()
.someModifier()
.someModifier()
.buttonStyle(.glassProminent)
} else {
Button()
.someModifier()
.someModifier()
.buttonStyle(.borderedProminent)
}
この書き方の問題点は、共通のモディファイア(.someModifier())が重複してしまうことです。共通部分が多くなればなるほど、コードの保守性が悪化します。
クロージャスタイルのModifierで楽に書く
シンプルな実装
この問題を解決するため、クロージャを受け取るシンプルな modifier(_:) を定義します。
extension View {
func modifier(@ViewBuilder _ closure: (Self) -> some View) -> some View {
closure(self)
}
}
この実装は非常にシンプルで、既存のSwiftUIのAPIと同じような感覚で使用できます。
使用例
クロージャスタイルの modifier(_:) を使うと、先ほどのコードを以下のように楽に書き直せます。
Button()
.someModifier()
.someModifier()
.modifier {
if #available(iOS 26.0, *) {
$0.buttonStyle(.glassProminent)
} else {
$0.buttonStyle(.borderedProminent)
}
}
Discussion