[Swift] MutableCollection.move を理解する

     

TAGS:

⌛️ 2 min.
MutableCollection の move の動作を説明 / 確認します。

環境&対象

以下の環境で動作確認を行なっています。

  • macOS Ventura 13.4 Beta
  • Xcode 14.3
  • iOS 16.4

MutableCollection.move

MutableCollection に move というメソッドが定義されています。

コレクション中の要素を IndexSet を使用して複数指定し、コレクション中の指定箇所に移動させることができるメソッドです。

Apple のドキュメントは、こちら
移動対象の要素指定に IndexSet を使用しているので、複数の要素を操作対象とできます。

まずは、単数指定から見ていきます。

単数対象

まずは、1つの要素が指定された時の動作を見てみます。

var array = [0,1,2,3,4,5]
array.move(fromOffsets: IndexSet([5]), toOffset: 4)
print(array) // [0, 1, 2, 3, 5, 4]

fromOffsets で指定している IndexSet が、移動対象要素の インデックスです。この場合は、5 を指定しているので、array[5] にある要素 “5” が移動対象です。

toOffset: 4 として指定されている 4 が 移動先です。
この 4 は、インデックスではあるのですが、配列要素 [4] の直前の位置 を指しています。(要素そのものではなく、その直前の位置情報を意味します)

NSString での index の説明図ですが、過去記事から引用します。

Index

詳細は、以下の記事で。
[Swift] String の位置指定を 理解する(String/String.Index と NSString/Int)

ですので、上記のサンプルのコードの結果として、[5] にある要素 “5” が、”4”の直前の位置に 挿入されています。

見ておくポイントの1つは、fromOffsets, toOffset いずれの指定も 操作前の情報をもとに指定されているということです。toOffset: 5 の指定は、fromOffsets で指定される要素の位置を考慮せずに指定することができます。(影響を考慮することが必要となると 4 と 5 の位置関係によって面倒な計算が必要になります。)

考慮しないで良いということは、前方方向だけではなく、面倒な計算なしに、後方にも移動させることができるということです。
例えば、[1] にある要素を [5] の直前に移動させようとすると以下のようになります。

var array = [0,1,2,3,4,5]
array.move(fromOffsets: IndexSet([1]), toOffset: 5)
print(array) // [0, 2, 3, 4, 1, 5]

なお、toOffset の引数は、その配列要素の”直前” を意味するため、要素数 6 の例題の配列に対して、toOffset: 6 を指定することで、最後尾を意味することになります。(配列への [6] アクセスは、もちろん Fatal Error です・・・)

var array = [0,1,2,3,4,5]
array.move(fromOffsets: IndexSet([4]), toOffset: 6)
print(array) // [0, 1, 2, 3, 5, 4]

意味はありませんが、配列中の要素を現在の位置に移動させるような以下のコードも実行可能です。結果として何も変更しません。

ちなみに、[4] を [4] の直前に移動させる書き方と、[4] を[5] の直前に移動させる書き方の2つがあります。

var array = [0,1,2,3,4,5]
array.move(fromOffsets: IndexSet([4]), toOffset: 4)
print(array) // [0, 1, 2, 3, 4, 5]

array.move(fromOffsets: IndexSet([4]), toOffset: 5)
print(array) // [0, 1, 2, 3, 4, 5]

複数対象

move は、移動対象として IndexSet を使って指定できるので、複数要素をまとめて move することが可能です。

その際に、順番は保持されます。

連続した位置にある要素の移動

まずは、連続した位置にある要素を指定してみます。

var array = [0,1,2,3,4,5]
array.move(fromOffsets: IndexSet([1,3,2]), toOffset: 5)
print(array) // [0, 4, 1, 2, 3, 5]

元の配列での要素の順番を保持して移動されていることがわかります。

連続していない位置にある要素の移動

非連続な位置にある要素を指定してみます。

var array = [0,1,2,3,4,5]
array.move(fromOffsets: IndexSet([2,0]), toOffset: 5)
print(array) // [1, 3, 4, 0, 2, 5]

非連続な位置にある要素を指定したときも、元の配列での順序を保持して移動していることがわかります。

まとめ

MutableCollection に定義されている move メソッドの動作を確認しました。

MutableCollection の move メソッド
  • fromOffsets では、移動対象の要素を指定する
  • fromOffsets には、IndexSet で複数要素を指定できる
  • toOffset は、移動先の指定
  • toOffset で指定した要素の直前に 要素が移動される

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

SwiftUI おすすめ本

SwiftUI を理解するには、以下の本がおすすめです。

SwiftUI ViewMatery

SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。

英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。

View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。

超便利です

SwiftUIViewsMastery

販売元のページは、こちらです。

SwiftUI 徹底入門

# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。

Swift学習におすすめの本

詳解Swift

Swift の学習には、詳解 Swift という書籍が、おすすめです。

著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。

最新版を購入するのがおすすめです。

現時点では、上記の Swift 5 に対応した第5版が最新版です。

コメントを残す

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