【SwiftUI】Listの行入れ替え

Listの行入れ替え処理の実現方法について解説します。

スポンサーリンク

環境

この記事の情報は次のバージョンで動作確認しています。

【Xcode】11.4.1
【Swift】5.2
【iOS】13.4.1
【macOS】Catalina バージョン 10.15.4

前提条件

行入れ替えを実現するには、次の3つの条件を満たしたリストが必要です。

  1. リストに関連付けられたコレクション(配列)が、@State等で宣言されており、更新可能である。
  2. List + ForEach でリストが生成されている。
    →行入れ替え処理はForEachのModifierを使って実現します。
  3. ForEachは範囲指定ではなくid指定による繰り返し。
    →各行の一意性が確保されている必要があります。

前提条件

編集モードの切り替えボタン追加

行入れ替え操作を行うには、リストを編集モードに切り替える必要があります。
その為に、編集モードの切り替えをするEditButtonを追加します。

以下はEditButtonをナビゲーションボタンとして配置した例です。

Editボタン追加

行入れ替え処理の追加

ForEachのonMove(perform:)で、行入れ替え時に呼び出すメソッド名を指定します。
呼び出し方は"(移動元:IndexSet, 移動先:Int) -> Void"の形式になります。

呼び出されるメソッド(rowReplace)には、コレクション(配列)の順序を入れ替える処理を記述します。
この中で使用しているmove(fromOffsets:, toOffset:)は、配列の順序を入れ替えるメソッドです。
このメソッドは、MutableCollectionプロトコルで宣言されており、iOS13以降でのみ使用可能です。

行入れ替え処理の追加

Editボタンを押して編集モードにすると、ドラッグで行入れ替えが可能になります。

Xcode11.4.1で上記サンプルを実行すると、1行上に移動させた時だけアニメーションの挙動がおかしい現象が発生します。
現象と対処方法をこちらにまとめましたので、御覧ください。
【SwiftUI】Listでセルをドラックする時の不具合
Listの並び替え操作時のアニメーションで、挙動がおかしいケースがあります。おそらくXcodeの今後のバージョンアップで解消すると思われますが、現時点での対処方法を残しておきます。

あわせて読みたい記事

【SwiftUI】Listの使い方
Listはデータの一覧表示をするのに適したViewです。画面に収まらない量の場合はスクロール表示になるなど、UIKitのUITableViewに似ていますが、はるかに簡単に使えます。ListはForEachとセットで使うケースが多いの...
【SwiftUI】Listの行削除
(2020/05/9 更新)Listで生成したデータ一覧の行削除処理について解説します。
【SwiftUI】ForEachの使い方(2/2)
ForEachの繰り返し処理にて出力したデータを変更(削除、並び替え)できるようにするには、SwiftUIが該当データを識別する為に、各要素の一意性が保証されている必要があります。本記事(2/2)では、各要素の一意性を保証したデータコレク...