【SwiftUI】カードみたいにコンテンツを表示をするときはGroupBoxを使うと便利だよ


## GroupBoxとは

今回は、SwiftUIの便利なViewのひとつ「GroupBox」を紹介します。

GroupBoxは意味のあるひとまとまりのコンテンツを視覚的にわかりやすく表示してくれるViewです。

言葉で説明するとわかりにくいので、Apple公式ドキュメントのサンプルをご覧ください。こちらのサンプルのように、カードのような見た目で表示してくれるコンポーネントです。
[GroupBox | Apple Developer Documentation](https://developer.apple.com/documentation/swiftui/groupbox)

![スクリーンショット 2024-10-29 14.46.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38924/fe0f970b-170f-3dbc-0a07-7a416f984213.png)

## GroupBoxを使ってみよう

こちらのサンプルはわたしがリリースした集中アプリのFocus Rainbowです。
Screen Time APIを使って、今集中したいアプリだけを実行することができます。
便利なタイマー機能や、楽しいキャラクターが集中をサポートしてくれるので、ぜひお試しください！

https://apps.apple.com/jp/app/focus-rainbow/id6569223924

Focus Rainbowではアプリの使い方のコツを紹介する画面を用意していて、その中に「自分のスマホを人に貸すときに大事なアプリをガードする」説明があります。
設定方法の手順を記載している箇所は、ひとまとまりの情報なのでスクリーンショットのように枠で囲っています。

![Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.23.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38924/d7bdfbdb-03f6-7079-1704-86ee96d4b2b4.png)


この部分のコードは、下記のとおりです。

``` Swift
    VStack(spacing: 10) {
        VStack(alignment: .leading, spacing: 20) {
            Text("1. アクティビティを追加します。")
            Text("2. アプリを選択ボタンをタップして、触っていいアプリだけを選んで登録します。")
            Text("3. 追加したアクティビティをタップして、集中するボタンをタップします。")
            Text("4. スマホを貸す時間を設定して、開始ボタンをタップします。")
            Text("5. ミッション完了！安心してスマホを渡せます。")
            Text("注意！")
                .font(.headline)
            Text("「大事なアプリをいつも使えるようにする」で紹介した方法で登録したアプリはガードされません。設定を見直すのをお忘れなく。")
        }
    }
    .padding()
    .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.accentColor, style: StrokeStyle(lineWidth: 1)))
    .clipShape(.rect(cornerRadius: 15))
```

では、このコードをGroupBoxに書き換えてみましょう。

``` Swift
    GroupBox {
        VStack(alignment: .leading, spacing: 10) {
            Text("1. アクティビティを追加します。")
            Text("2. アプリを選択ボタンをタップして、触っていいアプリだけを選んで登録します。")
            Text("3. 追加したアクティビティをタップして、集中するボタンをタップします。")
            Text("4. スマホを貸す時間を設定して、開始ボタンをタップします。")
            Text("5. ミッション完了！安心してスマホを渡せます。")
            Text("注意！")
                .font(.headline)
            Text("「大事なアプリをいつも使えるようにする」で紹介した方法で登録したアプリはガードされません。設定を見直すのをお忘れなく。")
        }
        .padding(.top)
    } label: {
        Label("設定方法", systemImage: "info.circle")
    }
```

GroupBoxに定義されている [init(content: label:)](https://developer.apple.com/documentation/swiftui/groupbox/init(content:label:)) というInitializerを使用しています。
contentにメインの情報を、labelにタイトル的な情報を設定します。

では、GroupBoxで書いたものを見てみましょう。
いい感じです。標準コンポーネントなので、ダークモード対応もバッチリですね。

|ライトモード|ダークモード|
|---|---|
|![Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.20.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38924/09d64b98-5818-88f0-cb7f-4be1e7951926.png)|![Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.24.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38924/f2688d2d-ad65-403a-aeee-d0db8053f79c.png)|



## GroupBoxStyleでカスタマイズ

ただ、元のサンプルとはだいぶ見た目が違うので、カスタマイズしてみましょう。
カスタマイズするときは、 [GroupBoxStyle](https://developer.apple.com/documentation/swiftui/groupbox/init(_:)) を使用します。

labelとcontentは左寄せにしたいので、VStackで囲んでalignmentを.leadingにしています。
また、アクセントカラーの枠線をつけて、角丸にしています。

``` Swift
struct RoundedCornerGroupBoxStyle: GroupBoxStyle {
    func makeBody(configuration: Configuration) -> some View {
        VStack(alignment: .leading) {
            configuration.label
            configuration.content
        }
        .padding()
        .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.accentColor, style: StrokeStyle(lineWidth: 1)))
        .clipShape(.rect(cornerRadius: 15))
    }
}
```

GroupBoxにGroupBoxStyleを適用するときは、 [groupBoxStyle(_:)](https://developer.apple.com/documentation/swiftui/view/groupboxstyle(_:)) を使用します。

``` Swift
    GroupBox {
        VStack(alignment: .leading, spacing: 10) {
            Text("1. アクティビティを追加します。")
// (中略)
        }
        .padding(.top)
    } label: {
        Label("設定方法", systemImage: "info.circle")
    }
    .groupBoxStyle(RoundedCornerGroupBoxStyle())
```

では、さっそく結果を見比べてみましょう。
いい感じですね。元のサンプルと同じようになりました。

| 元のサンプル|GroupBoxStyleで書いたもの|
|---|---|
|![Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.23.05 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38924/aa7acec9-e0ed-0a41-a6a0-d2f792cd3610.png)|![Simulator Screenshot - iPhone 16 - 2024-10-29 at 14.44.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38924/02263ce4-aa08-66c2-c7f0-2144175ea913.png)|

## まとめ

個人で開発しているアプリはできるだけAppleが提供しているコンポーネントを使って標準的なUIに近づけるように気をつけています。

標準的なUIに近いと、ユーザーは馴染みがあるのでとっつきやすくなります。また、標準のコンポーネントを使用すると、OSをアップデートしても壊れにくいですし、iPad OSやtvOSなど複数デバイス対応もやりやすくなります。

コンテンツのグループを作るときは、GroupBoxを試してみてください。