From 1df6447d7357691eabf05aa3d1c1bbd4c608549d Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 2 Sep 2016 21:09:28 +0300 Subject: [PATCH 1/8] set estimatedHeight nil by default --- Sources/ConfigurableCell.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/ConfigurableCell.swift b/Sources/ConfigurableCell.swift index 18035ff..5ec461e 100644 --- a/Sources/ConfigurableCell.swift +++ b/Sources/ConfigurableCell.swift @@ -42,7 +42,7 @@ public extension ConfigurableCell where Self: UITableViewCell { static var estimatedHeight: CGFloat? { get { - return UITableViewAutomaticDimension + return nil } } From aeae61d48b5c548a871aac57e080045cd58d483f Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 2 Sep 2016 21:11:30 +0300 Subject: [PATCH 2/8] remove checks in replace method --- Sources/TableCellAction.swift | 2 +- Sources/TableSection.swift | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Sources/TableCellAction.swift b/Sources/TableCellAction.swift index 8c81bef..5f12ca8 100644 --- a/Sources/TableCellAction.swift +++ b/Sources/TableCellAction.swift @@ -26,7 +26,7 @@ struct TableKitNotifications { /** A custom action that you can trigger from your cell. - You can eacily catch actions using a chaining manner with your row builder. + You can easily catch actions using a chaining manner with your row. */ public class TableCellAction { diff --git a/Sources/TableSection.swift b/Sources/TableSection.swift index 02ff134..904bfbd 100644 --- a/Sources/TableSection.swift +++ b/Sources/TableSection.swift @@ -84,13 +84,8 @@ public class TableSection { self.rows.insertContentsOf(rows, at: index) } - public func replace(rowAt index: Int, with row: Row) -> Bool { - - if index >= 0 && index < rows.count { - rows[index] = row - return true - } - return false + public func replace(rowAt index: Int, with row: Row) { + rows[index] = row } public func delete(index index: Int) { From 70d6cb8d737852372ce1f2bb8551af55552977b0 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 2 Sep 2016 21:16:36 +0300 Subject: [PATCH 3/8] TableCellManager -> TableCellRegisterer --- .../{TableCellManager.swift => TableCellRegisterer.swift} | 4 ++-- Sources/TableDirector.swift | 6 +++--- TableKit.xcodeproj/project.pbxproj | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) rename Sources/{TableCellManager.swift => TableCellRegisterer.swift} (98%) diff --git a/Sources/TableCellManager.swift b/Sources/TableCellRegisterer.swift similarity index 98% rename from Sources/TableCellManager.swift rename to Sources/TableCellRegisterer.swift index 891266e..393afa0 100644 --- a/Sources/TableCellManager.swift +++ b/Sources/TableCellRegisterer.swift @@ -20,8 +20,8 @@ import UIKit -class TableCellManager { - +class TableCellRegisterer { + private var registeredIds = Set() private weak var tableView: UITableView? diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift index 6f7c093..3cf11b6 100644 --- a/Sources/TableDirector.swift +++ b/Sources/TableDirector.swift @@ -30,7 +30,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate private weak var scrollDelegate: UIScrollViewDelegate? private var heightStrategy: CellHeightCalculatable? - private var cellManager: TableCellManager? + private var cellRegisterer: TableCellRegisterer? public var shouldUsePrototypeCellHeightCalculation: Bool = false { didSet { @@ -48,7 +48,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate super.init() if shouldUseAutomaticCellRegistration { - self.cellManager = TableCellManager(tableView: tableView) + self.cellRegisterer = TableCellRegisterer(tableView: tableView) } self.scrollDelegate = scrollDelegate @@ -123,7 +123,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate let row = sections[indexPath.section].rows[indexPath.row] - cellManager?.register(cellType: row.cellType, forCellReuseIdentifier: row.reuseIdentifier) + cellRegisterer?.register(cellType: row.cellType, forCellReuseIdentifier: row.reuseIdentifier) let cell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier, forIndexPath: indexPath) diff --git a/TableKit.xcodeproj/project.pbxproj b/TableKit.xcodeproj/project.pbxproj index 32e8324..fe0e2a7 100644 --- a/TableKit.xcodeproj/project.pbxproj +++ b/TableKit.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 50CF6E6B1D6704FE004746FF /* TableCellManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CF6E6A1D6704FE004746FF /* TableCellManager.swift */; }; + 50CF6E6B1D6704FE004746FF /* TableCellRegisterer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CF6E6A1D6704FE004746FF /* TableCellRegisterer.swift */; }; DA9EA7AF1D0EC2C90021F650 /* ConfigurableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7A61D0EC2C90021F650 /* ConfigurableCell.swift */; }; DA9EA7B01D0EC2C90021F650 /* HeightStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7A71D0EC2C90021F650 /* HeightStrategy.swift */; }; DA9EA7B11D0EC2C90021F650 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7A81D0EC2C90021F650 /* Operators.swift */; }; @@ -31,7 +31,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 50CF6E6A1D6704FE004746FF /* TableCellManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableCellManager.swift; sourceTree = ""; }; + 50CF6E6A1D6704FE004746FF /* TableCellRegisterer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableCellRegisterer.swift; sourceTree = ""; }; DA9EA7561D0B679A0021F650 /* TableKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TableKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DA9EA7A61D0EC2C90021F650 /* ConfigurableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurableCell.swift; sourceTree = ""; }; DA9EA7A71D0EC2C90021F650 /* HeightStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeightStrategy.swift; sourceTree = ""; }; @@ -89,7 +89,7 @@ isa = PBXGroup; children = ( DA9EA7AA1D0EC2C90021F650 /* TableDirector.swift */, - 50CF6E6A1D6704FE004746FF /* TableCellManager.swift */, + 50CF6E6A1D6704FE004746FF /* TableCellRegisterer.swift */, DA9EA7AB1D0EC2C90021F650 /* TableRow.swift */, DA9EA7AC1D0EC2C90021F650 /* TableRowAction.swift */, DA9EA7AE1D0EC2C90021F650 /* TableSection.swift */, @@ -225,7 +225,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 50CF6E6B1D6704FE004746FF /* TableCellManager.swift in Sources */, + 50CF6E6B1D6704FE004746FF /* TableCellRegisterer.swift in Sources */, DA9EA7AF1D0EC2C90021F650 /* ConfigurableCell.swift in Sources */, DA9EA7B31D0EC2C90021F650 /* TableDirector.swift in Sources */, DA9EA7B71D0EC2C90021F650 /* TableSection.swift in Sources */, From 1be65d18ad9dd8f1ff172ad7fcfd7b669cb47d5e Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 2 Sep 2016 21:42:34 +0300 Subject: [PATCH 4/8] PrototypeHeightStrategy improvements --- Sources/HeightStrategy.swift | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift index 66eec6f..f0f778d 100644 --- a/Sources/HeightStrategy.swift +++ b/Sources/HeightStrategy.swift @@ -49,7 +49,14 @@ public class PrototypeHeightStrategy: CellHeightCalculatable { return height } - guard let cell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier) else { return 0 } + var prototypeCell = prototypes[row.reuseIdentifier] + if prototypeCell == nil { + + prototypeCell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier) + prototypes[row.reuseIdentifier] = prototypeCell + } + + guard let cell = prototypeCell else { return 0 } cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height) @@ -66,7 +73,11 @@ public class PrototypeHeightStrategy: CellHeightCalculatable { } public func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat { - return UITableViewAutomaticDimension + + if let estimatedHeight = row.estimatedHeight where estimatedHeight > 0 { + return estimatedHeight + } + return height(row, path: path) } public func invalidate() { From 0f93d296ed516305b37160eba31a9394e04ab97d Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Fri, 2 Sep 2016 22:56:08 +0300 Subject: [PATCH 5/8] PrototypeHeightStrategy improvements --- .../Controllers/AutolayoutCellsController.swift | 3 ++- .../Presentation/Controllers/MainController.swift | 2 ++ .../Controllers/NibCellsController.swift | 1 + .../Presentation/Views/AutolayoutTableViewCell.swift | 9 ++++++++- Demo/Classes/Presentation/Views/NibTableViewCell.xib | 12 +++++++----- Sources/HeightStrategy.swift | 2 +- Sources/TableDirector.swift | 9 +++++---- 7 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Demo/Classes/Presentation/Controllers/AutolayoutCellsController.swift b/Demo/Classes/Presentation/Controllers/AutolayoutCellsController.swift index 618e02a..9340070 100644 --- a/Demo/Classes/Presentation/Controllers/AutolayoutCellsController.swift +++ b/Demo/Classes/Presentation/Controllers/AutolayoutCellsController.swift @@ -14,6 +14,7 @@ class AutolayoutCellsController: UIViewController { @IBOutlet weak var tableView: UITableView! { didSet { tableDirector = TableDirector(tableView: tableView) + tableDirector.shouldUsePrototypeCellHeightCalculation = true } } var tableDirector: TableDirector! @@ -26,7 +27,7 @@ class AutolayoutCellsController: UIViewController { let section = TableSection() var rows = 0 - while rows <= 10 { + while rows <= 1000 { rows += 1 let row = TableRow(item: ()) diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift index b57a0db..9c1534f 100644 --- a/Demo/Classes/Presentation/Controllers/MainController.swift +++ b/Demo/Classes/Presentation/Controllers/MainController.swift @@ -35,6 +35,8 @@ class MainController: UIViewController { } } + tableView.registerClass(ConfigurableTableViewCell.self, forCellReuseIdentifier: "ConfigurableTableViewCell") + let rows: [Row] = [ TableRow(item: "Autolayout cells", actions: [clickAction]), diff --git a/Demo/Classes/Presentation/Controllers/NibCellsController.swift b/Demo/Classes/Presentation/Controllers/NibCellsController.swift index 5309ebf..1b2f412 100644 --- a/Demo/Classes/Presentation/Controllers/NibCellsController.swift +++ b/Demo/Classes/Presentation/Controllers/NibCellsController.swift @@ -19,6 +19,7 @@ class NibCellsController: UITableViewController { title = "Nib cells" tableDirector = TableDirector(tableView: tableView) + //tableDirector.shouldUsePrototypeCellHeightCalculation = true let numbers = [1000, 2000, 3000, 4000, 5000] diff --git a/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift b/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift index ec505d6..491a949 100644 --- a/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift +++ b/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift @@ -20,7 +20,7 @@ class AutolayoutTableViewCell: UITableViewCell, ConfigurableCell { @IBOutlet var subtitleLabel: UILabel! static var estimatedHeight: CGFloat? { - return 500 + return 700 } func configure(with string: T) { @@ -28,4 +28,11 @@ class AutolayoutTableViewCell: UITableViewCell, ConfigurableCell { titleLabel.text = LoremIpsumTitle subtitleLabel.text = LoremIpsumBody } + + override func layoutSubviews() { + super.layoutSubviews() + + titleLabel.preferredMaxLayoutWidth = titleLabel.bounds.size.width + subtitleLabel.preferredMaxLayoutWidth = subtitleLabel.bounds.size.width + } } \ No newline at end of file diff --git a/Demo/Classes/Presentation/Views/NibTableViewCell.xib b/Demo/Classes/Presentation/Views/NibTableViewCell.xib index 1b9ae31..34c76d1 100644 --- a/Demo/Classes/Presentation/Views/NibTableViewCell.xib +++ b/Demo/Classes/Presentation/Views/NibTableViewCell.xib @@ -1,5 +1,5 @@ - + @@ -11,19 +11,21 @@ - + - - + + + + diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift index f0f778d..2aa4800 100644 --- a/Sources/HeightStrategy.swift +++ b/Sources/HeightStrategy.swift @@ -59,7 +59,7 @@ public class PrototypeHeightStrategy: CellHeightCalculatable { guard let cell = prototypeCell else { return 0 } cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height) - + row.configure(cell) cell.setNeedsLayout() diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift index 3cf11b6..88c90ea 100644 --- a/Sources/TableDirector.swift +++ b/Sources/TableDirector.swift @@ -98,14 +98,18 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let row = sections[indexPath.section].rows[indexPath.row] + + cellRegisterer?.register(cellType: row.cellType, forCellReuseIdentifier: row.reuseIdentifier) + return row.estimatedHeight ?? heightStrategy?.estimatedHeight(row, path: indexPath) ?? UITableViewAutomaticDimension } public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let row = sections[indexPath.section].rows[indexPath.row] + let rowHeight = invoke(action: .height, cell: nil, indexPath: indexPath) as? CGFloat - + return rowHeight ?? row.defaultHeight ?? heightStrategy?.height(row, path: indexPath) ?? UITableViewAutomaticDimension } @@ -122,9 +126,6 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let row = sections[indexPath.section].rows[indexPath.row] - - cellRegisterer?.register(cellType: row.cellType, forCellReuseIdentifier: row.reuseIdentifier) - let cell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier, forIndexPath: indexPath) if cell.frame.size.width != tableView.frame.size.width { From 29202d4405a1607cfdad4f74cd2cccccb691c640 Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Tue, 6 Sep 2016 19:30:47 +0300 Subject: [PATCH 6/8] height strategy improvements --- .../Controllers/NibCellsController.swift | 1 - .../Views/AutolayoutTableViewCell.swift | 4 +++- Sources/HeightStrategy.swift | 20 +++++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/Demo/Classes/Presentation/Controllers/NibCellsController.swift b/Demo/Classes/Presentation/Controllers/NibCellsController.swift index 1b2f412..5309ebf 100644 --- a/Demo/Classes/Presentation/Controllers/NibCellsController.swift +++ b/Demo/Classes/Presentation/Controllers/NibCellsController.swift @@ -19,7 +19,6 @@ class NibCellsController: UITableViewController { title = "Nib cells" tableDirector = TableDirector(tableView: tableView) - //tableDirector.shouldUsePrototypeCellHeightCalculation = true let numbers = [1000, 2000, 3000, 4000, 5000] diff --git a/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift b/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift index 491a949..ff4219e 100644 --- a/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift +++ b/Demo/Classes/Presentation/Views/AutolayoutTableViewCell.swift @@ -18,7 +18,7 @@ class AutolayoutTableViewCell: UITableViewCell, ConfigurableCell { @IBOutlet var titleLabel: UILabel! @IBOutlet var subtitleLabel: UILabel! - + static var estimatedHeight: CGFloat? { return 700 } @@ -32,6 +32,8 @@ class AutolayoutTableViewCell: UITableViewCell, ConfigurableCell { override func layoutSubviews() { super.layoutSubviews() + contentView.layoutIfNeeded() + titleLabel.preferredMaxLayoutWidth = titleLabel.bounds.size.width subtitleLabel.preferredMaxLayoutWidth = subtitleLabel.bounds.size.width } diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift index 2aa4800..66b715b 100644 --- a/Sources/HeightStrategy.swift +++ b/Sources/HeightStrategy.swift @@ -57,11 +57,10 @@ public class PrototypeHeightStrategy: CellHeightCalculatable { } guard let cell = prototypeCell else { return 0 } - - cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height) row.configure(cell) - + + cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height) cell.setNeedsLayout() cell.layoutIfNeeded() @@ -74,10 +73,19 @@ public class PrototypeHeightStrategy: CellHeightCalculatable { public func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat { - if let estimatedHeight = row.estimatedHeight where estimatedHeight > 0 { - return estimatedHeight + guard let tableView = tableView else { return 0 } + + let hash = row.hashValue ^ Int(tableView.bounds.size.width).hashValue + + if let height = cachedHeights[hash] { + return height } - return height(row, path: path) + + if let estimatedHeight = row.estimatedHeight where estimatedHeight > 0 { + return estimatedHeight + } + + return UITableViewAutomaticDimension } public func invalidate() { From eebaaf52689dda11b357dd41d66bd5fe27cac2cd Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Thu, 15 Sep 2016 01:08:52 +0300 Subject: [PATCH 7/8] remove useless cell registration --- Demo/Classes/Presentation/Controllers/MainController.swift | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift index 9c1534f..bad5564 100644 --- a/Demo/Classes/Presentation/Controllers/MainController.swift +++ b/Demo/Classes/Presentation/Controllers/MainController.swift @@ -34,9 +34,7 @@ class MainController: UIViewController { break } } - - tableView.registerClass(ConfigurableTableViewCell.self, forCellReuseIdentifier: "ConfigurableTableViewCell") - + let rows: [Row] = [ TableRow(item: "Autolayout cells", actions: [clickAction]), From 6a1650a68b36d65420ec1cca640274f1ea3c641c Mon Sep 17 00:00:00 2001 From: Max Sokolov Date: Thu, 15 Sep 2016 01:11:06 +0300 Subject: [PATCH 8/8] bump podspec and readme --- README.md | 2 +- TableKit.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2219125..c366ca1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Build Status Swift 2.2 compatible Carthage compatible - CocoaPods compatible + CocoaPods compatible Platform iOS License: MIT

diff --git a/TableKit.podspec b/TableKit.podspec index 06d3c55..5380a89 100644 --- a/TableKit.podspec +++ b/TableKit.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| s.name = 'TableKit' s.module_name = 'TableKit' - s.version = '1.1.2' + s.version = '1.2.0' s.homepage = 'https://github.com/maxsokolov/TableKit' s.summary = 'Type-safe declarative table views. Swift 2.2 is required.'