雑学1472593 views
高校日本史189857 views
LaTeX957300 views
中学社会667106 views
小学社会308636 views
世界の国560595 views
小学理科717236 views
英語607877 views
高校生物549842 views
中学英語808712 views
Help
Tools

English

削除・移動(onDelete, onMove)

SwiftUI の List では、onDeleteonMove モディファイアを使って行の削除と並び替えを簡単に実装できます。

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

特定の行だけ削除や移動を無効にしたい場合は、deleteDisabledmoveDisabled モディファイアを使います。

ForEach(items, id: \.self) { item in
    Text(item)
        .deleteDisabled(item == "重要")  // "重要" は削除不可
        .moveDisabled(item == "固定")    // "固定" は移動不可
}
.onDelete(perform: deleteItems)
.onMove(perform: moveItems)

これらのモディファイアを組み合わせることで、ユーザーがリストを自由に編集できるインタラクティブな UI を構築できます。