Listとは何か、SwiftUIのリストコンポーネント

著者: IT Sectr 公開日: 2026-06-25 読了時間: 7 分

Listは、SwiftUIでデータを垂直スクロール可能なリストとして表示するためのコンテナViewで、UIKitのUITableViewに相当します。Apple Developer Documentation, 2024によると、Listは静的および動的セクション、スワイプアクション、行の並べ替え、プル・トゥ・リフレッシュをサポートしています。UITableViewとは異なり、ListはSwiftUIとForEachに基づく宣言的APIを使用し、セルの再利用と多数の行に対するパフォーマンスを自動的に管理します。

重要ポイント

  • List — SwiftUIでスクロール可能なデータリストのためのコンテナ
  • ForEach — Listでデータを動的に表示する主要な方法
  • セクション — ヘッダー付きで行をグループ化するSection View
  • スワイプアクション — iOS 15+向けswipeActions
  • プル・トゥ・リフレッシュ — iOS 15+向け.refreshable

SwiftUIにおけるListとは?

Listは、アイテムのシーケンスを垂直スクロール可能なリストに表示するViewです。iOS 13でSwiftUIとともに導入され、UIKitのUITableViewを置き換えるデータリスト表示の主要な方法です。Listはセルの再利用、スクロール、パフォーマンスを自動的に管理します。

Listは遅延ロードを使用します:セルはスクロールに応じて作成され、一度に全てが作成されるわけではありません。これにより、ScrollView内のVStackとForEachとは異なり、レンダリング時にすべてのセルが作成されることはありません。Listはスワイプアクション、プル・トゥ・リフレッシュ、編集(削除/移動)、行選択の組み込みサポートも提供します。

Apple WWDC 2021(Session 10072)によると、iOS 15+のListは、コレクションレベルでの新しい差分メカニズムにより、大幅なパフォーマンス向上を実現しました。これにより、特に数百行のリストにおいて、データ更新時のListの効率が向上しました。

List vs ScrollView + VStack

開発者は、Viewのセットを表示する際にListとScrollView + VStackの間で選択することがよくあります。主な違い:Listはセルの再利用(UITableViewと同様)を使用しますが、ScrollView + VStackはすべてのViewを即座に作成します。固定サイズのリスト(最大20項目)の場合、違いはわずかです。50行以上の動的リストの場合、パフォーマンスの面でListが推奨されます。

静的リストと動的リスト

静的リストは、List本体で直接指定された固定数の行を持つリストです。メニュー、設定、既知のアイテムセットを持つフォームに使用されます。各行はループやForEachなしで明示的に宣言されます。

swift
// 静的リスト(メニューと設定用)
List {
    Text("プロフィール")
    Text("設定")
    Text("について")
}

// 動的リスト(データ用)
struct UserList: View {
    let users: [User]

    var body: some View {
        List(users) { user in
            HStack {
                Text(user.name)
                Text(user.role)
                    .foregroundColor(.secondary)
            }
        }
    }
}

動的リストは、List(data:rowContent:)イニシャライザまたはList本体内部のForEachを使用します。最初のアプローチは、各行が1つのデータ項目に対応する場合に便利です。2番目のアプローチは、データ間にセクションや追加の項目がある場合に役立ちます。

識別(Identifiable):動的リストの場合、データ項目はIdentifiableプロトコルに準拠するか、data:idタプルで一意の識別子へのKeyPathを指定する必要があります。SwiftUIは識別子を使用して変更(追加、削除、行の移動)を追跡します。

セクションとデータのグループ化

Sectionは、List内で行をヘッダーとオプションのフッターでグループ化するためのViewです。SectionはheaderとfooterをViewBuilderとして受け入れ、セクションヘッダーにテキストだけでなくカスタムViewを使用することもできます。

swift
struct SettingsView: View {
    var body: some View {
        List {
            Section(header: Text("アカウント")) {
                Text("名前")
                Text("メール")
            }
            Section(header: Text("通知")) {
                Toggle("Push", isOn: $pushEnabled)
                Toggle("Email", isOn: $emailEnabled)
            }
        }
        .listStyle(.insetGrouped)
    }
}

// ForEachを使用した動的セクション
List {
    ForEach(groupedData.keys.sorted(), id: \.self) { key in
        Section(header: Text(key)) {
            ForEach(groupedData[key]!) { item in
                Text(item.title)
            }
        }
    }
}

Listスタイル:SwiftUIは.listStyle()修飾子を介して複数の組み込みスタイルを提供します。.insetGrouped — iOS Settingsの標準、.plain — ミニマリスト、.inset — インデント付き、.sidebar — iPadのSidebar用。

SwiftUI Cookbook(2024)によると、動的セクションと内部にForEachを持つSectionは、複雑な構造を持つアプリケーションでデータをグループ化するための標準的なパターンです。重要なルール:SectionをSectionの中にネストしないでください。また、Sectionと一緒にList(data:)イニシャライザを使用しないでください — List本体の内部でForEachを使用してください。

スワイプアクションとプル・トゥ・リフレッシュ

.swipeActions(edge:allowsFullSwipe:content:) — iOS 15+向けの修飾子で、Listの行にスワイプアクションを追加します。左(デフォルト)または右にスワイプしたときに、異なる色と役割(destructive、cancel)を持つボタンを表示できます。

swift
struct TaskList: View {
    @Binding var tasks: [Task]

    var body: some View {
        List {
            ForEach($tasks) { $task in
                Text(task.title)
                    .swipeActions(edge: .trailing) {
                        Button("削除", role: .destructive) {
                            tasks.removeAll { $0.id == task.id }
                        }
                    }
                    .swipeActions(edge: .leading) {
                        Button(task.isDone ? "元に戻す" : "完了") {
                            task.isDone.toggle()
                        }
                        .tint(.green)
                    }
            }
        }
        .refreshable {
            // 非同期データ読み込み
            await loadTasks()
        }
    }
}

.refreshable — iOS 15+向けの修飾子で、プル・トゥ・リフレッシュを追加します。ユーザーがリストを下に引いたときに実行される非同期クロージャを受け入れます。SwiftUIは自動的にローディングインジケータを表示します。操作が完了すると、インジケータは非表示になります。

.onDeleteおよび.onMove — iOS 13+向けの修飾子で、行の削除と並べ替えのサポートを追加します。これらを使用するには、Bindingを使用してデータをForEachでラップするか、ListまたはForEachで.onDelete(perform:)を介してクロージャを渡します。

Listのパフォーマンスと最適化

Listのパフォーマンスは、行数、各セルの複雑さ、データ更新の頻度に依存します。SwiftUIは遅延ロードとセルの再利用(UITableView.dequeueReusableCellと同様)を使用しますが、500行以上のリストでは追加の最適化が必要になる場合があります。

最適化説明iOSバージョン
Identifiable各アイテムの一意のIDiOS 13+
EquatableViewデータが等しい場合の再描画を回避iOS 13+
id(_:)ID変更時にViewの再作成を強制iOS 13+
.equatable()Equatableによる厳密な比較iOS 15+
Diffable data変更時の自動差分検出iOS 15+

問題1:頻繁な更新。リスト内のデータが頻繁に更新される場合(例:毎秒)、Listは状態が変わるたびに表示セルを再描画する可能性があります。解決策:データに構造体(値型)を使用します — SwiftUIは値を比較し、変更された行のみを再描画します。

問題2:重いセル。各行に複雑なView階層、画像、アニメーションが含まれている場合、スクロールが遅くなる可能性があります。解決策:セルを個別のViewに抽出し、EquatableViewを使用して不要な再描画を防ぎます。SwiftUI Lab(2024)によると、複雑な行をサブコンポーネントに分割すると、レンダリング時間が30~50%短縮されます。

問題3:大量の行。1000行以上の場合、Listは遅延ロードにより効率的に動作しますが、レイアウト計算により初期ロードが遅くなる可能性があります。解決策:Listの機能(スワイプ、セクション)が必要ない均一な行のリストにはLazyVStackを使用します。フル機能のリストには、Listが最良の選択肢です。

よくある質問

SwiftUIにおけるListとは?

Listは、SwiftUIでスクロール可能なデータリストを表示するためのコンテナViewです。宣言的APIを持つUIKitのUITableViewに相当します。セクション、スワイプアクション、プル・トゥ・リフレッシュ、編集、.listStyle()によるカスタマイズをサポートしています。

ListとScrollView + VStackの違いは?

Listは遅延ロードとセルの再利用を使用します — セルはスクロールに応じて作成されます。ScrollView + VStackはすべてのViewを一度に作成します。50行以上のリストではListが推奨されます。固定の小規模セット(最大20項目)の場合、違いはわずかです。

Listにプル・トゥ・リフレッシュを追加するには?

.refreshable修飾子(iOS 15+)を使用します。データ更新ロジックを含む非同期クロージャを渡します。SwiftUIは自動的にローディングインジケータを表示し、非同期操作の完了後に非表示にします。

Listで行をグループ化するには?

ヘッダーとオプションのフッターを持つSection Viewを使用します。Section内にリスト行を配置します。動的セクションには、groupedDataとともにForEachを使用します。iOSのような外観にするには、.listStyle(.insetGrouped)でリストスタイルを設定します。

大量の行があるListを高速化するには?

データに構造体(値型)を使用し、複雑なセルをEquatableViewを持つ個別のViewに抽出し、各行での頻繁な状態更新を避けます。1000行以上のリストでListの機能が必要ない場合は、LazyVStackを検討してください。

まとめ

  • List — 遅延ロードとセルの再利用を備えたスクロール可能なリストのコンテナ
  • ForEach — Listでデータを動的に表示する主要な方法
  • Section — ヘッダーとフッターで行をグループ化
  • swipeActions — iOS 15+向けスワイプアクション
  • refreshable — iOS 15+向けプル・トゥ・リフレッシュ
  • スタイル — .listStyle()によるinsetGrouped、plain、inset、sidebar
  • パフォーマンス — Identifiable、EquatableView、値型を使用

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください