[SwiftUI] List の並べ替えの実装方法

SwiftUI

これまでは、リストの並べ替えの実装は、難しくないけれども面倒でした。
けれども、SwiftUI を使うと、非常に簡単に実装することができるので説明します。

List と ForEach と .onMove

使用する要素は、以下のものです。

使用する要素
  • List
  • ForEach
  • .onMove

普通のリスト表示には、List を使うかと思いますが、List での表示を、ForEach に分解します、その要素に対して、.onMove modifier を使って、どのように移動するかを実装します。




.onMove の実装

onMove に対しては、引数として、source :IndexSet と destination :Int が渡されてきます。

”どこから” ”どこへ” 移動させるかの情報です。

実は、Array の move メソッドは、同じ引数をとりますので、配列ないの順番入れ替えであれば、onMove で渡された引数をそのまま move に渡すと期待する動作になります。

onMove と move の実装

struct ContentView: View {
    @State private var dataList = ["item1", "item2", "item3"]
    var body: some View {
        List {
            ForEach( dataList, id: \.self) { data in
                Text(data)
                .padding()
            }
            .onMove(perform: self.move)
        }
    }
    
    func move(from source: IndexSet, to destination: Int) {
        dataList.move(fromOffsets: source, toOffset: destination)
    }
}

Mac と iOS での動作の違い

Mac 上では、上記のコードだけで、リストの要素の入れ替えが可能となります。

iOS では、リストのスクロールとジェスチャーが重複していますので、明示的にエディットモードに入る必要があります。

エディットモードは、environment の .editMode で制御することができますので、iOS では、以下のようにすると並べ替え操作を行うことができます。

コード


struct ContentView: View {
    @State private var dataList = ["item1", "item2", "item3"]
    var body: some View {
        List {
            ForEach( dataList, id: \.self) { data in
                Text(data)
                .padding()
            }
            .onMove(perform: self.move)
        }
        .environment(\.editMode, .constant(.active))      // ⬅️ iOS 対応
    }
    
    func move(from source: IndexSet, to destination: Int) {
        dataList.move(fromOffsets: source, toOffset: destination)
    }
}

上記では、常に active にしていますが、通常は、エディットモード切り替えをリストのタイトル部分等に表示して実装します。




注意点: macOS で使う時に気をつけること

macOS で不用意に使うと 想定しないクラッシュが発生することがあります。

SwiftUI[SwiftUI] List/ForEach の onMove についての メモ書きSwiftUI[SwiftUI] onMove を自分で実装する

自分で実装することも難しくはないので、検討した方が良いです。

まとめ:List の要素の並べ替えの実装方法のポイントは4つ

以下の点を考慮することで、非常に簡単に実装できます。

  • ForEach の要素に対して、onMove を設定する
  • onMove でデータソースのリスト要素の並べ替えを行う
  • データソースが Array であれば、Array の move 関数を使うと非常に簡単に実装できる
  • iOS であれば、.editMode を設定しないと、並べ替えモードにならない

説明は、以上です。




コメントを残す

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