はじめに
SwiftUIのListについて公式ドキュメントの内容をまとめてみました
環境
Xcode 13.4.1
内容
List
とは、1つの列に並んだデータの行を表示するコンテナで、オプションで1つ以上のメンバーを選択する機能を提供する
struct List<SelectionValue, Content> where SelectionValue : Hashable, Content : View
var body: some View {
List {
Text("A List Item")
Text("A Second List Item")
Text("A Third List Item")
}
}

一般的には、Identifiable
に準拠したデータから動的にリストを作成する
struct Ocean: Identifiable {
let name: String
let id = UUID()
}
private var oceans = [
Ocean(name: "Pacific"),
Ocean(name: "Atlantic"),
Ocean(name: "Indian"),
Ocean(name: "Southern"),
Ocean(name: "Arctic")
]
var body: some View {
List(oceans) {
Text($0.name)
}
}

選択可能なリスト
リストのメンバーを選択可能にするには、選択変数へのバインディングを提供する。リストデータのIdentifiable.ID型の単一のインスタンスにバインドすると、単一選択のリストが、セットへのバインディングは、複数の選択をサポートするリストを作成する
struct Ocean: Identifiable, Hashable {
let name: String
let id = UUID()
}
private var oceans = [
Ocean(name: "Pacific"),
Ocean(name: "Atlantic"),
Ocean(name: "Indian"),
Ocean(name: "Southern"),
Ocean(name: "Arctic")
]
@State private var multiSelection = Set<UUID>()
var body: some View {
NavigationView {
List(oceans, selection: $multiSelection) {
Text($0.name)
}
.navigationTitle("Oceans")
.toolbar { EditButton() }
}
Text("\(multiSelection.count) selections")
}


タップやクリックで1つ選択すると、選択されたセルの外観が変わり、選択されたことが示される。タップ操作で複数選択できるようにするには、editModeの値を変更するか、アプリのインターフェースにEditButtonを追加して、リストを編集モードにする。リストを編集モードにすると、各リスト項目の横に丸印が表示され、ユーザーが関連する項目を選択すると、円にはチェックマークが入る
リストの更新
標準のrefreshコントロールを使ってリストの内容を更新可能にするには、 refreshable(action:)
を使用する
ユーザーがリストのトップを下にドラッグすると、リフレッシュコントロールを表示し、指定されたアクションを実行する。データをリフレッシュするためにアクションクロージャの内部でawait式を使用、リフレッシュインジケータは待機している操作の間、表示されたままとなる
struct Ocean: Identifiable, Hashable {
let name: String
let id = UUID()
let stats: [String: String]
}
class OceanStore: ObservableObject {
@Published var oceans = [Ocean]()
func loadStats() async {
oceans .append(Ocean(name: "hoge", stats: ["hoge":"hoge"]))
}
}
struct ContentView: View {
@EnvironmentObject var store: OceanStore
var body: some View {
NavigationView {
List(store.oceans) { ocean in
HStack {
Text(ocean.name)
StatsSummary(stats: ocean.stats)
}
}
.refreshable {
await store.loadStats()
}
.navigationTitle("Oceans")
}
}
}
struct StatsSummary: View {
@State var stats: [String: String]
var body: some View {
Text(stats.description)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(OceanStore())
}
}



リストのセクション分け
2 次元リストを作成するには、セクションインスタンス内の項目をグループ化する
struct ContentView: View {
struct Sea: Hashable, Identifiable {
let name: String
let id = UUID()
}
struct OceanRegion: Identifiable {
let name: String
let seas: [Sea]
let id = UUID()
}
private let oceanRegions: [OceanRegion] = [
OceanRegion(name: "Pacific",
seas: [Sea(name: "Australasian Mediterranean"),
Sea(name: "Philippine"),
Sea(name: "Coral"),
Sea(name: "South China")]),
OceanRegion(name: "Atlantic",
seas: [Sea(name: "American Mediterranean"),
Sea(name: "Sargasso"),
Sea(name: "Caribbean")]),
OceanRegion(name: "Indian",
seas: [Sea(name: "Bay of Bengal")]),
OceanRegion(name: "Southern",
seas: [Sea(name: "Weddell")]),
OceanRegion(name: "Arctic",
seas: [Sea(name: "Greenland")])
]
@State private var singleSelection: UUID?
var body: some View {
NavigationView {
List(selection: $singleSelection) {
ForEach(oceanRegions) { region in
Section(header: Text("Major \(region.name) Ocean Seas")) {
ForEach(region.seas) { sea in
Text(sea.name)
}
}
}
}
.navigationTitle("Oceans and Seas")
}
}
}

アコーディオン(階層のある)リスト
ツリー構造のデータと、任意のレベルの子ノードを取得するためのキーパスを提供するchildrenパラメータを提供することにより、任意の深さの階層的リストを作成することができる。折りたたみ式のセルを使用して、ユーザーがツリー構造をナビゲートできるようになっている
struct ContentView: View {
struct FileItem: Hashable, Identifiable, CustomStringConvertible {
var id: Self { self }
var name: String
var children: [FileItem]? = nil
var description: String {
switch children {
case nil:
return "📄 \(name)"
case .some(let children):
return children.isEmpty ? "📂 \(name)" : "📁 \(name)"
}
}
}
let fileHierarchyData: [FileItem] = [
FileItem(name: "users", children:
[FileItem(name: "user1234", children:
[FileItem(name: "Photos", children:
[FileItem(name: "photo001.jpg"),
FileItem(name: "photo002.jpg")]),
FileItem(name: "Movies", children:
[FileItem(name: "movie001.mp4")]),
FileItem(name: "Documents", children: [])
]),
FileItem(name: "newuser", children:
[FileItem(name: "Documents", children: [])
])
]),
FileItem(name: "private", children: nil)
]
var body: some View {
List(fileHierarchyData, children: \.children) { item in
Text(item.description)
}
}
}




リストのスタイル
SwiftUI はプラットフォームとリストが表示されるビュータイプに基づいてリストの表示スタイルを選ぶ。ビュー内のすべてのリストに異なる ListStyle を適用するには、listStyle(_:)
修飾子を使用する
static var automatic: DefaultListStyle
プラットフォームのデフォルトの動作とリストの外観を記述するリストスタイル
static var grouped: GroupedListStyle
static var inset: InsetListStyle
static var insetGrouped: InsetGroupedListStyle
グループ化されたインセットリストの動作と外観を記述するリストスタイル
static var plain: PlainListStyle
static var sidebar: SidebarListStyle
おわりに
この記事を見る限りList
はすでにLazy
であるようなので、カスタマイズに問題がなければList
をどんどん使っていこうと思いました
参考