UIデータソースの最新情報

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_views

iOS13までのTableView/CollectionViewの更新における問題

UI層がControllerに対してTableView/CollectionViewのSection数, Item数を要求するだけでなく、
Controllerは外部(Modelなど)からデータ追加などの変更が発生したことUI層に伝えるなど、
双方向にデータが流れる
これにより、TableView/CollectionViewのSection, Item数の整合性が合わなくなりcrashする可能性がある。
reloadDataを使うと、Animationが損なわれる

Diffable Data Source

上記の問題点やパフォーマンス改善のためのiOS13から利用可能な新しいAPI

Diffable Data Sourceの利用方法

NSDiffableDataSourceSnapshotの初期化

NSDiffableDataSourceSnapshot
// NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable
var snapshot = NSDiffableDataSourceSnapshot<SectionType, ItemType>()
SectionTypeとItemTypeはHashable protocolに準拠する必要があります sample code
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/3375763-appendsections
https://developer.apple.com/documentation/uikit/nsdiffabledatasourcesnapshot/3375762-appenditems

追加したSection, Itemsの反映

dataSource.apply(snapshot, animatingDifferences: true)
https://developer.apple.com/documentation/uikit/uicollectionviewdiffabledatasource/3375795-apply

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からコールしないこと
最新情報をチェックしよう!