Chasinget - かなり素晴らしい小さなプロジェクト
- ジョエル・レビン
これは、Dave Delongの記事に概説されているソリューションを実装しようとする試みであり、距離を編集し、手順を編集します。
Changeset 、 Equatable要素のCollectionから別の要素に移動するために必要な最小限の編集について説明します。
これは、主に、2つのデータセット間の追加、削除、置換、および移動を検出することにより、 UITableViewおよびUICollectionViewデータソースと併用するために使用されています。ただし、2つのデータセット間でより一般的な変更を計算するためにも使用できます。
次のコードは、 Stringコレクション「子猫」から「座って」に移動する標準的な例の最小編集を計算します。
let changeset = Changeset ( source : " kitten " , target : " sitting " )
print ( changeset )
// 'kitten' -> 'sitting':
// replace with s at offset 0
// replace with i at offset 4
// insert g at offset 6その後、次のアサーションが成功します。
let edits = [
Changeset < String > . Edit ( operation : . substitution , value : " s " , destination : 0 ) ,
Changeset < String > . Edit ( operation : . substitution , value : " i " , destination : 4 ) ,
Changeset < String > . Edit ( operation : . insertion , value : " g " , destination : 6 ) ,
]
assert ( changeset . edits == edits )ソースコレクションとターゲットコレクションも保存するChangeset自体のオーバーヘッドが必要ない場合は、 editsを直接呼び出すことができます(ここでは、iOSのAppleのテーブルビュープログラミングガイドの例を使用して):
let source = [ " Arizona " , " California " , " Delaware " , " New Jersey " , " Washington " ]
let target = [ " Alaska " , " Arizona " , " California " , " Georgia " , " New Jersey " , " Virginia " ]
let edits = Changeset . edits ( from : source , to : target )
print ( edits )
// [insert Alaska at offset 0, replace with Georgia at offset 2, replace with Virginia at offset 4]Changesetは、インデックスではなくオフセットを使用して、コレクション内の要素を参照することに注意してください。これは主に、Swiftコレクションがゼロベースの整数インデックスを使用することが保証されていないためです。詳細については、第37号の議論を参照してください。
オフセット値は、 UITableViewのbeginUpdates / endUpdatesのアニメーションブロックで直接使用でき、 UICollectionViewのChangeset performBatchUpdatesは、Appleのガイドの行とセクションのバッチ挿入、削除、およびリロードで説明されている原則に従います。
要するに;まず、ソースコレクションに対して、結果のコレクション、挿入を比較して、すべての削除と置換が作成されます。移動とは、削除に続いて挿入が続くだけです。
iOSフレームワークでは、アニメーション化されたテーブル/コレクションビューの更新を簡単にするために、2つのコンビニエンスエクステンション(1つはUITableViewとUICollectionViewに1つ)が含まれています。このようにupdateを呼び出すだけです:
tableView . update ( with : changeset . edits ) デフォルトでは、 Changeset ==を使用して要素を比較しますが、以下に示す独自のコンパレータを書くことができます。「A」の発生が常に変更をトリガーします。
let alwaysChangeA : ( Character , Character ) -> Bool = {
if $0 == " a " || $1 == " a " {
return false
} else {
return $0 == $1
}
}
let changeset = Changeset ( source : " ab " , target : " ab " , comparator : alwaysChangeA )その結果、Changesetは「A」(別の「A」へ)の置換で構成されます。
let expectedEdits : [ Changeset < String > . Edit ] = [ Changeset . Edit ( operation : . substitution , value : " a " , destination : 0 ) ]
assert ( changeset . edits == expectedEdits )これの使用可能な1つは、 UITableViewまたはUICollectionViewのセルが変更されたときにアニメーション化しない場合です。
Xcodeプロジェクトには、アプリの使用法を説明するためのターゲットも含まれています。

これは、上記の拡張機能を使用して、 Changesetの編集に基づいて遷移をアニメーション化します。
このプロジェクトは、MITライセンスの下で入手できます。
Copyright©2015-18、Joachim Bondo。ライセンスファイルを参照してください。