目次
Advances in UI Data Sources
https://developer.apple.com/videos/play/wwdc2019/220/概要
UI Data Sourcesを使用すると、自動差分出力機能によってTableView/CollectionView Itemの更新を合理化することが出来る。Itemの更新は追加のコードなしで高い品質の自動アニメーション可能。
このUI Data Sourcesの利用により、Itemの同期におけるバグや例外、クラッシュを回避することが出来、Appの動的なデータとコンテンツの開発に注力することが出来る
Apple公式 Sample code
https://developer.apple.com/documentation/uikit/views_and_controls/collection_views/implementing_modern_collection_viewsiOS13までのTableView/CollectionViewの更新における問題
UI層がControllerに対してTableView/CollectionViewのSection数, Item数を要求するだけでなく、Controllerは外部(Modelなど)からデータ追加などの変更が発生したことUI層に伝えるなど、
双方向にデータが流れる
これにより、TableView/CollectionViewのSection, Item数の整合性が合わなくなりcrashする可能性がある。
reloadDataを使うと、Animationが損なわれる

Diffable Data Source
上記の問題点やパフォーマンス改善のためのiOS13から利用可能な新しいAPIDiffable Data Sourceの利用方法
NSDiffableDataSourceSnapshotの初期化
NSDiffableDataSourceSnapshot// NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable
var snapshot = NSDiffableDataSourceSnapshot<SectionType, ItemType>()
enum Section: CaseIterable {
case main
}
class MountainsController {
struct Mountain: Hashable {
let name: String
let height: Int
let identifier = UUID()
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
}
...
var dataSource = UICollectionViewDiffableDataSource<Section, MountainsController.Mountain>()
Section, Itemの追加
snapshot.appendSections([.main])
snapshot.appendItems(mountains)
https://developer.apple.com/documentation/uikit/nsdiffabledatasourcesnapshot/3375762-appenditems
追加したSection, Itemsの反映
dataSource.apply(snapshot, animatingDifferences: true)
Diffable Data Sourceのパフォーマンス
- Safe to call
apply()
from a background queue - main queueでの線形diffに多くの時間がかかる場合、background queueからapply()をコールする
- background queueからapply()をコールすると、frameworkはmain queueにいると認識し、diff計算を続け、計算が終わるとmain queueに戻る
- background queueでのapply()コール時の注意点
Always call exclusively from the main queue or a background queue
Framework will log or assert
- background queueからコールした後は,一貫してbackground queueを使用し、main queueからコールしないこと