[SwiftUI]Listの編集

3 min read読了の目安(約3300字

SwiftUIで編集可能なListの作成方法をまとめました。
簡単な方法と少し複雑な方法の2通りがあります。ボタンの見た目にこだわるなら後者を使用します。

EditButtonを使う方法

EditButtonを使うと簡単に編集可能なListが作れます。

struct ContentView: View {
    
    @State private var fruits = ["apple", "orange", "banana", "pineapple", "strawberry", "mango", "melon"]
    
    var body: some View {
        NavigationView {
            
            List {
                ForEach.init(fruits, id: \.self) { fruit in
                    Text(fruit)
                }.onDelete(perform: { indexSet in
                    self.fruits.remove(atOffsets: indexSet)
                }).onMove(perform: { indices, newOffset in
                    self.fruits.move(fromOffsets: indices, toOffset: newOffset)
                })
            }
            .navigationBarTitle("Edit List", displayMode: .inline)
            .navigationBarItems(trailing: EditButton())
            
        }
    }
}

ポイントは以下の3つです

  • EditButtonを使う
  • onDeleteを追加することで要素の削除が可能
  • onMoveを追加することで要素の移動が可能

見た目は以下のようになります。

通常 編集モード

EditButtonを使うと、簡単に編集が実装できることがわかります。
この方法だと、EditButtonの文言がローカライズ以外変更できないデメリットがあります。

EditModeを使う方法

EnvironmentValuesには編集状態を管理するEditModeがあります。

public enum EditMode {
    case inactive
    case transient
    case active
    public var isEditing: Bool { get }
}
extension EnvironmentValues {
    public var editMode: Binding<EditMode>?
}

状態管理のための変数を自分で定義し、Viewに対して.environmentで適用すればEditModeを自分で変更することができます。

struct ContentView: View {
    
    @State private var fruits = ["apple", "orange", "banana", "pineapple", "strawberry", "mango", "melon"]
    
    @State var editMode: EditMode = .inactive
    
    var body: some View {
        NavigationView {
            
            List {
                ForEach.init(fruits, id: \.self) { fruit in
                    Text(fruit)
                }.onDelete(perform: { indexSet in
                    self.fruits.remove(atOffsets: indexSet)
                }).onMove(perform: { indices, newOffset in
                    self.fruits.move(fromOffsets: indices, toOffset: newOffset)
                })
            }
            .navigationBarTitle("Edit List", displayMode: .inline)
            .navigationBarItems(trailing: Button.init(action: { self.editMode = self.editMode.isEditing ? .inactive : .active }, label: {
                if self.editMode.isEditing {
                    Image.init(systemName: "checkmark")
                } else {
                    Image.init(systemName: "square.and.pencil")
                }
            }))
            .environment(\.editMode, self.$editMode)
            
        }
    }
}

上記のようにEditModeを使うことで、ボタンのデザインを変えることができます。

通常 編集モード

サンプルコード

https://github.com/usk-sample/EditListSample

参考

https://developer.apple.com/documentation/swiftui/editbutton
https://developer.apple.com/documentation/swiftui/environmentvalues/editmode
https://developer.apple.com/documentation/swiftui/editmode
https://developer.apple.com/documentation/swiftui/environmentvalues