【SwiftUI】onMoveとは?使い方や引数の意味、活用シーンをわかりやすく解説!

SwiftUIでリストの要素を並べ替える機能を実装したいときに便利なのが .onMove() です。

ドラッグ&ドロップ操作でユーザーが要素の順序を自由に変更できるようになるため、チェックリストやタスク管理アプリなど多くの場面で活用できます。

この記事では、.onMove() の基本的な使い方、引数の意味、活用シーンをわかりやすく解説します。

.onMove() とは?

.onMove() は、SwiftUI の List 内で並べ替え可能な状態を実現するためのモディファイアです。

具体的には、ユーザーがリスト上の要素をドラッグして移動させたときに、データの順序を更新する処理を受け取ることができます。

UIKitであれば UITableView に対して編集モードや delegate メソッドを設定する必要がありましたが、SwiftUIでは .onMove() を使うだけで非常に簡単に導入できます。

基本的な使い方

まず基本的な使い方を確認していきましょう。

1. シンプルな文字列配列の並べ替え

以下は、文字列の配列を並べ替え可能なリストとして表示する例です。

このコードでは、ユーザーが対象のアイテムをドラッグ&ドロップで移動させることができます。

下記はシミュレーターの例なのでポインターで動かしていますが、実際は指でドラッグ&ドロップして並び替えられます。

onMove1

ユーザーがドラッグするとonMove(perform:) に渡した move 関数が呼ばれ、配列の要素が新しい順番に更新されて並び替えが行われます。

EditButtonを使わない並べ替え

iOS 15以降では、特定の条件下で EditButton を使って編集モードにしなくても、.onMove() だけでドラッグ操作が有効になりました。

ただし、使用する場合は以下の点に注意が必要です:

  • 条件: List内にSectionがない、シンプルな構造の場合に有効
  • 推奨: 確実な動作のためには EditButton の使用を推奨
  • 明示的指定: .moveDisabled(false) で明示的にドラッグを有効化(指定しなくても並び替えできるが複雑な構造は明示的に指定を推奨)

.onMove(perform:) の仕組みと引数の意味

.onMove(perform:)「ユーザーがリストをドラッグで並び替えたときに呼び出される処理」 を受け取ります。

ここで.onMove(perform:)が受け取るのは「並び替えのロジックを記述した関数」や「無名クロージャ」です。

クロージャのシグネチャ

.onMove(perform:) は、この moveItems 関数(関数名はmoveなど別名でもOK)を 引数として受け取る ことができます。

言い換えると、moveItems は「ユーザー操作に応じて呼ばれる処理の中身」を担当し、その参照を .onMove に渡している形になります。

SwiftUI 側でドラッグ操作が発生すると、内部で moveItems(from:to:) が呼び出され、データを並び替える処理が実行されます。

役割を整理すると下記となります。

  • .onMove = 「ユーザーが並び替えたときに呼ぶよ、と登録する場所」
  • moveItems = 「並び替えが起きたときに実際にどう処理するかを書く関数」

つまり、.onMove(perform: moveItems) と書くことで、イベントハンドラとして moveItems を渡している、という構造です。

並び替えが起きた時に処理する関数は下記2つの引数を受け取ります。

引数名 説明
source IndexSet 移動対象となる要素のインデックス(複数選択可能)
destination Int 移動先のインデックス

私がこの引数を見た時に下記のような疑問が出たので、そちらも備忘録として記載しておきます。

  • IndexSet って何?
    複数の整数インデックスをまとめて管理するためのコレクション型です。連続した範囲やバラバラのインデックスを一度に保持できます。
  • なぜ sourceIndexSet なのか?
    リスト上で複数の要素を同時に移動できるようにするためです。ユーザーが一度に複数のアイテムを選択してドラッグした場合にも対応できます。

  • なぜ destinationInt なのか?
    移動先は「最終的に挿入される位置」を示す単一の場所だけを指定すれば十分だからです。
    複数の要素を動かす場合でも、そのまとまりが新しく配置される位置はひとつのインデックスで表現できます。

注意点とベストプラクティス

.onMove(perform:) を使う際の注意点とベストプラクティを簡単にまとめます。

必須要件

  • ForEachList の直下にある必要がある
  • データには一意の id が必要(.selfUUID など)
  • 配列のデータは @State などで状態管理する必要がある

推奨事項

  • 確実な動作のため EditButton() を使用する
  • 複雑なレイアウトでは .moveDisabled(false) を明示する
  • アニメーションを追加してユーザビリティを向上させる
  • 大量データの場合はパフォーマンスを考慮する

避けるべき書き方

まとめ

.onMove() は SwiftUI でユーザーによる並べ替え機能を簡単に実装できる強力なモディファイアです。

重要なポイント:

  • .onMove() は List 上で並べ替え可能な状態を作る
  • move(fromOffsets:toOffset:) を使って配列の順序を更新
  • 確実な動作には EditButton の使用を推奨
  • 複雑なレイアウトでは .moveDisabled(false) を明示
  • データは必ず @State などで状態管理する

タスク管理アプリ、チェックリスト、カスタマイズ可能なメニューなど、ユーザーが順序を自由に変更できる機能を簡単に実装できます。

まずは基本的な使い方から始めて、段階的に複雑な機能を追加していくのがおすすめです!

おすすめの記事