Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Diffing inside SwiftUI List

Diffing inside SwiftUI List

2019/08/07 Bonfire iOS #6
Twitter hashtag: #yjbonfire

Ryo Aoyama

August 07, 2019
Tweet

More Decks by Ryo Aoyama

Other Decks in Programming

Transcript

  1. Diffing inside SwiftUI List 2019.08.07 WED 
 Bonfire iOS #6

    #yjbonfire Ryo Aoyama GitHub: @ra1028 Twitter: @ra1028fe5
  2. PROFILE Ryo Aoyama Cyberagent, Inc Ὂ CATS iOS Lead Ὂ

    WinTicket OSS Author Ὂ DifferenceKit, Carbon, VueFlux, etc… GitHub: @ra1028 Twitter: @ra1028fe5
  3. struct ContentView: View { var body: some View { List(["A",

    "B", "C", "D"]) { text in Text(text) } } }
  4. let window = UIWindow(windowScene: windowScene) let controller = UIHostingController(rootView: ContentView())

    window.rootViewController = controller self.window = window window.makeKeyAndVisible() dump(controller.view)
  5. ▿ some: <_TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView: 0x7f92d586d800; baseClass = UITableView; frame = (0

    0; 375 812); clipsToBounds = YES; tintColor = UIExtendedSRGBColorSpace 0 0.478431 1 1; gestureRecognizers = <NSArray: 0x600001eb0660>; layer = <CALayer: 0x6000010af340>; contentOffset: {0, -44}; contentSize: {375, 177.33333333333334}; adjustedContentInset: {44, 0, 34, 0}; dataSource: <_TtGC7SwiftUIP13$7fff2c7391a819ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_S2__: 0x7f92d3f13860>> #47 - super: UITableView - super: UIScrollView - super: UIView - super: UIResponder - super: NSObject Ұ෦ൈਮ
  6. swift demangle _TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView _TtC7SwiftUIP33_BFB370BA5F1BADDC9D83021565761A4925UpdateCoalescingTableView ---> SwiftUI.(UpdateCoalescingTableView in _BFB370BA5F1BADDC9D83021565761A49) swift demangle

    _TtGC7SwiftUIP13_7fff2c7391a819ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_S2__ _TtGC7SwiftUIP13_7fff2c7391a819ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_S2__ ---> SwiftUI.(ListCoreCoordinator in _7fff2c7391a8)<SwiftUI.SystemListDataSource<Swift.Never>, Swift.Never> demangle
  7. func extractTableView(from view: UIView) -> UITableView? { if let tableView

    = view as? UITableView { return tableView } for view in view.subviews { if let tableView = extractTableView(from: view) { return tableView } } return nil } dump(extractTableView(from: controller.view)?.dataSource)
  8. ▿ some: <_TtGC7SwiftUIP13$7fff2c7391a819ListCoreCoordinatorGVS_20SystemListDataSourceOs5Never_S2__: 0x7fd686e11490> #0 ▿ super: SwiftUI.PlatformViewCoordinator - super:

    NSObject ▿ dataSource: SwiftUI.SystemListDataSource<Swift.Never> ▿ sections: SwiftUI.Sections ▿ offsets: 1 element ... - hasExplicitSections: false - sectionsWithFooters: 0 members ▿ ids: ... ▿ super: ... ▿ base: ... Ұ෦ൈਮ
  9. ▿ updates: SwiftUI.ListCoreBatchUpdates<SwiftUI.SystemListDataSource<Swift.Never>> ▿ removeSections: 0 indexes - ranges: 0

    elements ▿ insertSections: 0 indexes - ranges: 0 elements - moveSections: 0 elements - removeRows: 0 elements - insertRows: 0 elements - moveRows: 0 elements - isEmpty: true ▿ base: [] - rawUpdates: 0 elements ▿ sectionChanges: [] - pathStorage: 0 elements - pathStartIndex: 0 ▿ rowChanges: [] - pathStorage: 0 elements - pathStartIndex: 0 - movedSectionCandidates: 0 key/value pairs - movedRowCandidates: 0 key/value pairs Ұ෦ൈਮ
  10. enum Section { case main } enum Item: String, CaseIterable

    { case a, b, c } @IBOutlet var tableView: UITableView! lazy var dataSource = UITableViewDiffableDataSource<Section, Item>(tableView: tableView) { tableView, indexPath, item in let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = item.rawValue return cell }
  11. enum Section { case main } enum Item: String, CaseIterable

    { case a, b, c } @IBOutlet var tableView: UITableView! lazy var dataSource = UITableViewDiffableDataSource<Section, Item>(tableView: tableView) { tableView, indexPath, item in let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = item.rawValue return cell } SectionͱCellͷIDΛදݱ͢ΔܕͰHashableʹ ४ڌ͢Δඞཁ͕͋Δ
  12. struct Item: Hashable { var text: String var flag: Bool

    func hash(into hasher: inout Hasher) { hasher.combine(text) } static func == (lhs: Item, rhs: Item) -> Bool { lhs.text == rhs.text } } IDͱͯ͠ৼΔ෣͏஋(text)ͷଞʹ༨ܭͳ஋(flag)Λ΋ͭܕΛ࡞Γɺ Hashableͷ൑ఆ͔Βআ֎ͨ͠஋ΛSnapshotʹ௥Ճͯ͠ΈΔ (আ֎͠ͳ͍৔߹ͷࠩ෼͸delete + insertͱͯ͠ѻΘΕΔ) snapshot.appendItems([ Item(text: "A", flag: false), Item(text: "B", flag: false), Item(text: "C", flag: false) ])
  13. public init<Data, RowContent>(_ data: Data, selection: Binding<Selection>?, action: @escaping (Data.Element.IdentifiedValue)

    -> Void, rowContent: @escaping (Data.Element.IdentifiedValue) -> RowContent) where Content == ForEach<Data, Button<HStack<RowContent>>>, Data: RandomAccessCollection, RowContent: View, Data.Element: Identifiable SwiftUI.List
  14. protocol Identifiable { associatedtype ID : Hashable var id: Self.ID

    { get } associatedtype IdentifiedValue = Self var identifiedValue: Self.IdentifiedValue { get } } Identifiable
  15. Author Myers Wu Heckel Order O(ND) O(NP) O(N) Insert ✅

    ✅ ✅ Delete ✅ ✅ ✅ Move ⚠ ⚠ ✅ Update ❌ ❌ ✅ http://www.xmailserver.org/diff2.pdf http://documents.scribd.com/docs/10ro9oowpo1h81pgh1as.pdf https://publications.mpi-cbg.de/Wu_1990_6334.pdf Major Diff Algorithms