[SwiftUI] List の要素削除 の実装方法

SwiftUI

List で要素を表示していると、左スワイプで削除 という操作は非常に自然なインターフェースです。
このインターフェースを簡単に実装する方法を説明します。

リスト表示には、List を使います

SwiftUI の List を使うことで、要素をリスト表示することができます。

List を使ったリスト表示

struct ListView: View {
  var names = ["First", "Second", "Third"]
  
  var body: some View {
    VStack {
      List(names, id:\.self) { name in
        Text(name)
      }
      .navigationBarTitle("List only")
    }
    .padding()
  }
}

List でリスト表示

「List でリスト表示」

EditMode で、.active になる必要があります

編集モードにするためには、.environment の .EditMode を設定する必要があります。

SwiftUI には、EditButton という要素が用意されていて、そのボタンを表示することで、ユーザー操作で切り替えることができます。

# NavigationBar に表示するために、親ビューで NavigationView を指定しています。

EditButton 付きリスト表示

struct ListView: View {
  @State var names = ["First", "Second", "Third"]
  
  var body: some View {
    VStack {
      List(names, id:\.self) { name in
        Text(name)
      }
      .navigationBarTitle("List only")
    }
    .navigationBarItems(trailing: EditButton())
    .padding()
  }
}

List でリスト表示

「EditButtonWithList」

List と EditButton では不十分

動作を確認してみると、Edit ボタンを押しても、何も変わらないことがわかります。

期待しているのは、Edit ボタンを押すことで、以下のように、各行の左側に、削除マークが表示されることです。

削除マーク付きのリスト表示 編集モード

「削除マーク付きのリスト表示 編集モード」

ForEach

このインターフェースを手軽に実装するには、List の中で、ForEach を使って表示していることが必要となります。
具体的には、ForEach のもつ、onDelete を実装している必要があります。

ForEach を List の内側でネストさせ、ForEach に対して onDelete を実装することで、削除のための UI が表示されるようになります。

ForEach を使った List ビュー onDelete 付き

struct ListForEachView: View {
  @State var names = ["First", "Second", "Third"]

  var body: some View {
      VStack {
        List {
          ForEach(names, id: \.self) { name in
            Text(name)
          }
          .onDelete(perform: { indexSet in
            names.remove(at: indexSet.first!)
          })
        }
        .navigationBarTitle("Names")
      }
      .navigationBarItems(trailing: EditButton())
      .padding()
  }
}

ForEach を使ったList onDelete 実装済み

「ForEach を使ったList onDelete 実装済み」
削除ボタンを押下する削除だけでなく、左スワイプによる削除もサポートされます。

このように、ForEach と onDelete を組み合わせることで、標準的な削除インターフェースを組み込むことができます。

サンプルコード

以下のコードで、実際に試すことができます。

そのまま動くサンプルコード

//
//  ContentView.swift
//  EditMode
//
//  Created by Tomoaki Yagishita on 2020/10/08.
//

import SwiftUI

struct ContentView: View {
  var body: some View {
    NavigationView {
      VStack {
        NavigationLink("List View", destination: ListView())
          .padding()
        NavigationLink("List with ForEach View", destination: ListForEachView())
          .padding()
      }
      .padding()
    }
  }
}
struct ListView: View {
  @State var names = ["First", "Second", "Third"]
  
  var body: some View {
    VStack {
      List(names, id:\.self) { name in
        Text(name)
      }
      .navigationBarTitle("List only")
    }
    .navigationBarItems(trailing: EditButton())
    .padding()
  }
}

struct ListForEachView: View {
  @State var names = ["First", "Second", "Third"]

  var body: some View {
      VStack {
        List {
          ForEach(names, id: \.self) { name in
            Text(name)
          }
          .onDelete(perform: { indexSet in
            names.remove(at: indexSet.first!)
          })
        }
        .navigationBarTitle("Names")
      }
      .navigationBarItems(trailing: EditButton())
      .padding()
  }
}
struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

まとめ

標準的なリスト上での削除インターフェースの使い方
  • ForEach を使った List 表示を行う
  • EditButton を使った .environment の .EditMode を使用した編集モードを使用する
  • onDelete を実装する

説明は以上です。
不明な点やおかしな点ありましたら、ご連絡いただけるとありがたいです。

SwiftUI本

SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
以下の”SwiftUI Views Mastery Bundle"という本がビジュアル的に確認して探せるので、超便利です。

SwiftUIViewsMastery

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です