SwiftUI の List では、onDelete と onMove モディファイアを使って行の削除と並び替えを簡単に実装できます。
onDelete による削除
onDelete は ForEach に適用し、スワイプで削除する機能を追加します。
struct ContentView: View { @State private var items = ["りんご", "みかん", "バナナ", "ぶどう"] var body: some View { List { ForEach(items, id: \.self) { item in Text(item) } .onDelete(perform: deleteItems) } } func deleteItems(at offsets: IndexSet) { items.remove(atOffsets: offsets) } }
onDelete のクロージャには IndexSet が渡されます。remove(atOffsets:) メソッドで該当インデックスの要素を削除できます。
onMove による並び替え
onMove で行のドラッグ&ドロップによる並び替えを実装します。
struct ContentView: View { @State private var items = ["項目1", "項目2", "項目3", "項目4"] var body: some View { NavigationStack { List { ForEach(items, id: \.self) { item in Text(item) } .onMove(perform: moveItems) } .toolbar { EditButton() } } } func moveItems(from source: IndexSet, to destination: Int) { items.move(fromOffsets: source, toOffset: destination) } }
並び替えを有効にするには EditButton を配置するか、編集モードに入る必要があります。
削除と並び替えの組み合わせ
実際のアプリでは削除と並び替えを両方サポートすることが多いです。
struct TodoListView: View { @State private var tasks = ["買い物", "掃除", "洗濯", "料理"] var body: some View { NavigationStack { List { ForEach(tasks, id: \.self) { task in Text(task) } .onDelete(perform: deleteTasks) .onMove(perform: moveTasks) } .navigationTitle("タスク") .toolbar { EditButton() } } } func deleteTasks(at offsets: IndexSet) { tasks.remove(atOffsets: offsets) } func moveTasks(from source: IndexSet, to destination: Int) { tasks.move(fromOffsets: source, toOffset: destination) } }
EditButton
タップすると List が編集モードに入り、削除ボタンとドラッグハンドルが表示される。
編集モード以外での削除
onDelete を設定すると、編集モードでなくてもスワイプで削除できる。
編集モードをコードで制御
EditMode 環境変数を使えば、編集モードをプログラムから制御できます。
struct ContentView: View { @State private var items = ["A", "B", "C"] @State private var editMode: EditMode = .inactive var body: some View { NavigationStack { List { ForEach(items, id: \.self) { item in Text(item) } .onDelete { items.remove(atOffsets: $0) } .onMove { items.move(fromOffsets: $0, toOffset: $1) } } .environment(\.editMode, $editMode) .toolbar { Button(editMode.isEditing ? "完了" : "編集") { withAnimation { editMode = editMode.isEditing ? .inactive : .active } } } } } }
deleteDisabled と moveDisabled
特定の行だけ削除や移動を無効にしたい場合は、deleteDisabled と moveDisabled モディファイアを使います。
ForEach(items, id: \.self) { item in Text(item) .deleteDisabled(item == "重要") // "重要" は削除不可 .moveDisabled(item == "固定") // "固定" は移動不可 } .onDelete(perform: deleteItems) .onMove(perform: moveItems)
これらのモディファイアを組み合わせることで、ユーザーがリストを自由に編集できるインタラクティブな UI を構築できます。