中学英語809495 views
中学社会667457 views
小学社会308942 views
高校生物550226 views
小学算数1196702 views
りんご197191 views
高校日本史190006 views
教育149067 views
高校倫理1434987 views
高校物理158628 views

SwiftUI モディファイアの適用順序

SwiftUI のモディファイアは、適用する順序によって結果が大きく変わる。これは SwiftUI の根本的な仕組みに関わる重要な概念で、理解しないと意図しないレイアウトに悩まされることになる。

モディファイアは「ラップ」する

SwiftUI のモディファイアは、元のビューを新しいビューで包み込む。チェーンの各ステップで新しいビューが生成される。

Text("Hello")
    .padding()
    .background(.blue)

このコードは、Text を Padding でラップし、さらにそれを Background でラップしている。結果として、青い背景はパディングを含む領域に適用される。

Text("Hello")
    .background(.blue)
    .padding()

順序を入れ替えると、青い背景は Text のみに適用され、パディングは背景の外側に追加される。

視覚的な違いを確認

// パターン A: padding → background
Text("A")
    .padding(20)
    .background(.red)

// パターン B: background → padding
Text("B")
    .background(.red)
    .padding(20)
パターン A

テキストの周りにパディングがあり、その全体が赤い背景で覆われる。背景は大きい。

パターン B

テキストだけが赤い背景で覆われ、その外側にパディングがある。背景は小さい。

frame の順序

frame も同様に順序が重要だ。

Text("Hello")
    .frame(width: 200, height: 100)
    .background(.green)
    .frame(width: 300, height: 150)
    .background(.orange)

最初の frame で 200×100 の領域が確保され、緑の背景がそこに適用される。次の frame で 300×150 に拡大され、オレンジの背景は拡大後の領域に適用される。緑の矩形がオレンジの矩形の中央に配置された、入れ子構造になる。

クリッピングと角丸

cornerRadius(または clipShape)と frame の順序も影響を受ける。

// 角丸が内側に
Image("photo")
    .resizable()
    .frame(width: 100, height: 100)
    .clipShape(RoundedRectangle(cornerRadius: 20))

// 角丸が外側に
Image("photo")
    .resizable()
    .clipShape(RoundedRectangle(cornerRadius: 20))
    .frame(width: 100, height: 100)

最初の例では、100×100 にリサイズしてから角丸でクリップする。2 番目は先にクリップしてからリサイズするため、角丸の比率が変わる可能性がある。

影の順序

shadow も順序の影響を受ける典型例だ。

Text("Shadow")
    .padding()
    .background(.white)
    .shadow(radius: 5)  // 背景全体に影

Text("Shadow")
    .padding()
    .shadow(radius: 5)  // テキストだけに影
    .background(.white)

shadow はそれより上のモディファイアで構成されたビュー全体に適用される。background を shadow の後に置くと、背景には影がつかない。

複数の同じモディファイア

同じモディファイアを複数回使うこともできる。

Text("Nested")
    .padding(10)
    .background(.red)
    .padding(10)
    .background(.blue)
    .padding(10)
    .background(.green)

赤→青→緑と入れ子になった背景が作られる。これを利用して、ボーダー風の効果を作ることもできる。

overlay と background

overlay と background も順序に注意が必要だ。

Rectangle()
    .fill(.blue)
    .frame(width: 100, height: 100)
    .overlay(
        Circle().fill(.red).frame(width: 50, height: 50)
    )
    .padding()

overlay は「その時点でのビュー」の上に重ねる。padding を overlay の後に置くと、赤い円は青い四角形の中央に配置されたまま、全体にパディングが追加される。

実用的なガイドライン

レイアウト系は内側から

frame、padding などは、コンテンツに近い位置から適用していくのが基本。

装飾系は対象の直後

background、border、shadow は、装飾したいビューの直後に置く。

クリッピングは最後

clipShape は、最終的なサイズが決まった後に適用するのが一般的。

モディファイアの順序を意識することで、予測可能なレイアウトが実現できる。迷ったときは、各ステップで background(.red.opacity(0.3)) などを挟んでデバッグすると、どの段階でどのサイズになっているかが可視化できる。