From f1b30368744dab5f288c7e636d8bd64a41012e40 Mon Sep 17 00:00:00 2001 From: Daniele Margutti Date: Wed, 22 Aug 2018 12:11:51 +0200 Subject: [PATCH] #4 Fixes for assertion in TableDirector update. Use performBatchUpdates in iOS 11+ --- .../Table Example/TableViewController.swift | 30 +++++++------ Sources/Flow/Table/TableDirector.swift | 44 ++++++++++++------- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/ExampleApp/Table Example/TableViewController.swift b/ExampleApp/Table Example/TableViewController.swift index 42e9972..7db1e36 100644 --- a/ExampleApp/Table Example/TableViewController.swift +++ b/ExampleApp/Table Example/TableViewController.swift @@ -15,19 +15,7 @@ class TableViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let articleAdpt = TableAdapter() - articleAdpt.on.dequeue = { ctx in - ctx.cell?.titleLabel?.text = ctx.model.title - ctx.cell?.subtitleLabel?.text = ctx.model.text - } - articleAdpt.on.tap = { ctx in - print("Tapped on article \(ctx.model.id)") - return .deselectAnimated - } - self.tableView?.director.register(adapter: articleAdpt) - - - + self.tableView?.director.register(adapter: ArticleAdapter()) self.tableView?.director.add(section: self.getWinnerSection()) self.tableView?.director.rowHeight = .autoLayout(estimated: 100) @@ -82,6 +70,22 @@ class TableViewController: UIViewController { } +public class ArticleAdapter: TableAdapter { + + init() { + super.init() + self.on.dequeue = { ctx in + ctx.cell?.titleLabel?.text = ctx.model.title + ctx.cell?.subtitleLabel?.text = ctx.model.text + } + self.on.tap = { ctx in + print("Tapped on article \(ctx.model.id)") + return .deselectAnimated + } + } + +} + public class Article: ModelProtocol, Hashable { public var hashValue: Int { return self.id.hashValue diff --git a/Sources/Flow/Table/TableDirector.swift b/Sources/Flow/Table/TableDirector.swift index 8c92eee..639c7bc 100644 --- a/Sources/Flow/Table/TableDirector.swift +++ b/Sources/Flow/Table/TableDirector.swift @@ -154,6 +154,7 @@ public class TableDirector: NSObject, UITableViewDelegate, UITableViewDataSource return } + // Keep a reference to removed items in order to perform diff and animation let oldSections: [TableSection] = Array.init(self.sections) var oldItemsInSections: [String: [ModelProtocol]] = [:] @@ -162,26 +163,37 @@ public class TableDirector: NSObject, UITableViewDelegate, UITableViewDataSource // Execute callback and return animations to perform let animationsToPerform = (t(self) ?? TableReloadAnimations.default()) - // Execute reload for sections - let changesInSection = SectionChanges.fromTableSections(old: oldSections, new: self.sections) - changesInSection.applyChanges(toTable: self.tableView, withAnimations: animationsToPerform) - - self.tableView?.beginUpdates() - self.sections.enumerated().forEach { (idx,newSection) in - if let oldSectionItems = oldItemsInSections[newSection.UUID] { - guard let oldItems = oldSectionItems as? [AnyHashable], let newItems = newSection.models as? [AnyHashable] else { - debugPrint("Malfunction: models in table must be conform to Hashable protocol in order to perform automatic diff") - return + func executeDiffAndUpdate() { + // Execute reload for sections + let changesInSection = SectionChanges.fromTableSections(old: oldSections, new: self.sections) + changesInSection.applyChanges(toTable: self.tableView, withAnimations: animationsToPerform) + + self.sections.enumerated().forEach { (idx,newSection) in + if let oldSectionItems = oldItemsInSections[newSection.UUID] { + guard let oldItems = oldSectionItems as? [AnyHashable], let newItems = newSection.models as? [AnyHashable] else { + debugPrint("Malfunction: models in table must be conform to Hashable protocol in order to perform automatic diff") + return + } + // models must conform to Hashable otherwise we are not able to perform diff + let diffData = diff(old: oldItems, new: newItems) + let itemChanges = SectionItemsChanges.create(fromChanges: diffData, section: idx) + itemChanges.applyChangesToSectionItems(ofTable: self.tableView, withAnimations: animationsToPerform) } - // models must conform to Hashable otherwise we are not able to perform diff - let diffData = diff(old: oldItems, new: newItems) - let itemChanges = SectionItemsChanges.create(fromChanges: diffData, section: idx) - itemChanges.applyChangesToSectionItems(ofTable: self.tableView, withAnimations: animationsToPerform) } } - self.tableView?.endUpdates() - DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: { onEnd?() }) + if #available(iOS 11.0, *) { + self.tableView?.performBatchUpdates({ + executeDiffAndUpdate() + }, completion: { end in + if end { onEnd?() } + }) + } else { + self.tableView?.beginUpdates() + executeDiffAndUpdate() + self.tableView?.endUpdates() + DispatchQueue.main.asyncAfter(deadline: .now() + 0.25, execute: { onEnd?() }) + } } /// Change the content of the table.