SwiftUI ViewModifier プロトコル
ViewModifier プロトコルは、ビューに対する変更をカプセル化して再利用可能にする仕組みだ。複数のモディファイアをまとめたり、条件に応じた装飾を定義したりする際に活用する。
ViewModifier の基本構造
ViewModifier プロトコルは body(content:) メソッドを要求する。content は元のビューを表し、それに変更を加えて返す。
struct CardStyle: ViewModifier {
func body(content: Content) -> some View {
content
.padding()
.background(.white)
.cornerRadius(12)
.shadow(radius: 4)
}
}この CardStyle を適用すると、パディング、白背景、角丸、影がまとめて適用される。
modifier() で適用
ViewModifier は .modifier() を使って適用する。
Text("カード内のテキスト")
.modifier(CardStyle())ただし、毎回 .modifier() と書くのは冗長なので、View の extension を用意するのが一般的だ。
extension View {
func cardStyle() -> some View {
modifier(CardStyle())
}
}
// 使用
Text("カード内のテキスト")
.cardStyle()パラメータを持つ ViewModifier
ViewModifier にプロパティを持たせて、動的な設定を可能にできる。
struct RoundedBorder: ViewModifier {
var color: Color
var width: CGFloat
var cornerRadius: CGFloat
func body(content: Content) -> some View {
content
.overlay(
RoundedRectangle(cornerRadius: cornerRadius)
.stroke(color, lineWidth: width)
)
}
}
extension View {
func roundedBorder(
color: Color = .gray,
width: CGFloat = 1,
cornerRadius: CGFloat = 8
) -> some View {
modifier(RoundedBorder(
color: color,
width: width,
cornerRadius: cornerRadius
))
}
}デフォルト値を設定しておけば、呼び出し側で必要なパラメータだけ指定できる。
Text("デフォルト")
.roundedBorder()
Text("カスタム")
.roundedBorder(color: .blue, width: 2, cornerRadius: 16)環境変数を使った ViewModifier
ViewModifier 内で @Environment を使って、環境に応じた動作を実装できる。
struct AdaptiveStyle: ViewModifier {
@Environment(\.colorScheme) var colorScheme
func body(content: Content) -> some View {
content
.padding()
.background(colorScheme == .dark ? Color.gray : Color.white)
.cornerRadius(8)
}
}ダークモードとライトモードで自動的に背景色が切り替わる。
条件付きの ViewModifier
ViewModifier 内で条件分岐を行い、状態に応じた装飾を適用できる。
struct HighlightModifier: ViewModifier {
var isHighlighted: Bool
func body(content: Content) -> some View {
content
.padding(isHighlighted ? 16 : 8)
.background(isHighlighted ? Color.yellow.opacity(0.3) : Color.clear)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(isHighlighted ? Color.yellow : Color.clear, lineWidth: 2)
)
}
}
extension View {
func highlight(_ isHighlighted: Bool) -> some View {
modifier(HighlightModifier(isHighlighted: isHighlighted))
}
}Text("重要な項目")
.highlight(isImportant)concat で ViewModifier を連結
複数の ViewModifier を concat で連結できる。
struct CombinedModifier: ViewModifier {
func body(content: Content) -> some View {
content.modifier(CardStyle().concat(RoundedBorder(
color: .blue,
width: 1,
cornerRadius: 12
)))
}
}ただし、実際には extension で複数のモディファイアを順に呼ぶ方が可読性は高い。
いつ ViewModifier を使うか
複数のモディファイアをまとめたい。アプリ全体で統一したスタイルを定義したい。パラメータ化して再利用したい。
1〜2 個のモディファイアを適用するだけ。特定の場所でしか使わない一度きりの装飾。
ViewModifier はデザインシステムの構築に欠かせない機能だ。カードスタイル、ボタンスタイル、入力フィールドスタイルなどをモディファイアとして定義しておけば、アプリ全体で一貫した見た目を維持しやすくなる。












