先日の記事で List の並び替えについて onMove アクションについて紹介しました。onMove の引数 perform: には以下のフォーマットのメソッドを指定する必要があることも説明しました。
(from source: IndexSet, to destination: Int) -> Void
リストの並び替えを完了するだけであれば、リストの元データ配列の move メソッドに source と destination を渡せば済みます。
self.(配列).move(fromOffsets: source, toOffset: destination)
ただし、データの並び順を各データごとに持たせたりする場合、並び替え後にsource と destination を使って全体の並び順データを更新する必要があります。
筆者も開発中にその必要性が生じたので、source と destination にどのような値が入っているか調べてみました。
source と destination の値を確認してみる
先日の記事で使った物と同じですが、以下のコードで試してみました。
struct ContentView: View {
@State private var languages = [
"C/C++",
"Java",
"C#",
"Ruby",
"PHP",
"Objective-C",
"Swift",
"Kotlin",
"Python"
]
var body: some View {
NavigationView {
List {
ForEach(languages, id: \.self) { lang in
Text(lang)
}
.onMove(perform: move)
}
.navigationBarItems(trailing: EditButton())
}
}
func move(from source: IndexSet, to destination: Int) {
self.languages.move(fromOffsets: source, toOffset: destination)
print("source:\(source.first!)")
print("destination:\(destination)")
}
}
print で source と destination の値を出力しました(source は IndexSet 型なので first から取得します)。
まず、上から下へ並び替えた場合です。
リストを0始まりとして考えた場合、source の方は 2 なので画面上の順と一致します。しかし、destination は 6 なので画面上の順と一致しません。
「そうか、destination は 1始まりのルールなのだな」とこの時点ではそう思いました。
次に下から上への並び替えです。
おや?今度は source も destination も0始まりのように見えます。
同様に、いろいろなパターンを試してみましたが、何度やっても、上から下に並び替えする場合と下から上に並び替えする場合で、destination だけ値が異なりました。
理由を調べたり考えたりしてみましたが、どうもよくわからず仕舞いです。
0始まりの値として考えたかったので、仕方なく、上から下へ並び替えする場合は destination を -1 することで対処しています。
バグなのか、はたまたちゃんと意味があるのか、どなたかご存知の方がいらっしゃいましたらコメント下さい。
以上
コメントを残す