From 8b5ad2fcd1a4c50fb56dcb1ce0dfaceaa8862e15 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Mon, 13 Jun 2016 16:07:12 +0300
Subject: [PATCH 01/29] update readme
---
README.md | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index a691198..c3c8d7e 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,12 @@
#TableKit
-
-
-
-
-
+
+
+
+
+
+
TableKit is a super lightweight yet powerful generic library that allows you to build complex table views in a declarative type-safe manner.
@@ -113,6 +114,8 @@ pod 'TableKit'
```
#### Carthage
Add the line `github "maxsokolov/tablekit"` to your `Cartfile`
+#### Manual
+Clone the repo and drag files from `Sources` folder into your Xcode project.
## Requirements
From 1ed3db1cb1ab7741bbe8b561a358c75e299eb642 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Mon, 13 Jun 2016 16:21:16 +0300
Subject: [PATCH 02/29] update readme
---
Demo/Classes/Presentation/Controllers/MainController.swift | 4 ++++
README.md | 6 +++++-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift
index d2b4cab..b5c4881 100644
--- a/Demo/Classes/Presentation/Controllers/MainController.swift
+++ b/Demo/Classes/Presentation/Controllers/MainController.swift
@@ -41,6 +41,10 @@ class MainController: UIViewController {
row1
.addAction(TableRowAction(.shouldHighlight) { (data) -> Bool in
+ data.cell
+ data.item
+ data.path
+
print("1")
return false
diff --git a/README.md b/README.md
index c3c8d7e..ab571c6 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,10 @@ It nice to have some actions that related to your cells:
```swift
let action = TableRowAction(.click) { (data) in
+ // you could access any useful information that relates to the action
+ // data.cell - StringTableViewCell?
+ // data.item - String
+ // data.path - NSIndexPath
}
let row = TableRow(item: "some", actions: [action])
@@ -113,7 +117,7 @@ use_frameworks!
pod 'TableKit'
```
#### Carthage
-Add the line `github "maxsokolov/tablekit"` to your `Cartfile`
+Add the line `github "maxsokolov/tablekit"` to your `Cartfile`.
#### Manual
Clone the repo and drag files from `Sources` folder into your Xcode project.
From 3e4f7d81ff6f52a57d07d10b72abe861416036d9 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Mon, 13 Jun 2016 16:34:57 +0300
Subject: [PATCH 03/29] remove configure action
---
Demo/Classes/Presentation/Controllers/MainController.swift | 6 +-----
Sources/TableRowAction.swift | 1 -
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift
index b5c4881..bec8ab6 100644
--- a/Demo/Classes/Presentation/Controllers/MainController.swift
+++ b/Demo/Classes/Presentation/Controllers/MainController.swift
@@ -40,11 +40,7 @@ class MainController: UIViewController {
row1
.addAction(TableRowAction(.shouldHighlight) { (data) -> Bool in
-
- data.cell
- data.item
- data.path
-
+
print("1")
return false
diff --git a/Sources/TableRowAction.swift b/Sources/TableRowAction.swift
index d4d10b7..cd3f0c6 100644
--- a/Sources/TableRowAction.swift
+++ b/Sources/TableRowAction.swift
@@ -26,7 +26,6 @@ public enum TableRowActionType {
case select
case deselect
case willSelect
- case configure
case willDisplay
case shouldHighlight
case height
From 7cc572c7aafbc658db198a60833c2d278b501eaa Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Tue, 14 Jun 2016 16:07:49 +0300
Subject: [PATCH 04/29] update readme
---
README.md | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index ab571c6..170adf3 100644
--- a/README.md
+++ b/README.md
@@ -22,15 +22,14 @@ It hides a complexity of `UITableViewDataSource` and `UITableViewDelegate` metho
- [x] Automatic xib/classes registration
- [x] No need to subclass
- [x] Extensibility
-- [x] Tests
-## Usage
+## Getting Started
Create your rows:
```swift
let row1 = TableRow(item: "1")
-let row2 = TableRow(item: 2)
-let row3 = TableRow(item: 3.0)
+let row2 = TableRow(item: 2)
+let row3 = TableRow(item: 3.0)
```
Put rows into section:
```swift
From cc75e84f5839697a264c679a22b4352bda9a6675 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Tue, 14 Jun 2016 20:47:39 +0300
Subject: [PATCH 05/29] try height strategy
---
Sources/HeightStrategy.swift | 12 ++++++------
Sources/TableDirector.swift | 8 +++++++-
Sources/TableRow.swift | 2 +-
3 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index c34bd40..9072767 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -20,25 +20,25 @@
import UIKit
-public protocol HeightStrategy {
+public protocol HeightCalculatingStrategy {
var tableView: UITableView? { get set }
- func height- (item: Item, indexPath: NSIndexPath, cell: Cell.Type) -> CGFloat
+ func height(indexPath: NSIndexPath, reusableIdentifier: String, configure: (cell: UITableViewCell) -> Void) -> CGFloat
}
-public class PrototypeHeightStrategy: HeightStrategy {
+public class PrototypeHeightStrategy {
public weak var tableView: UITableView?
private var cachedHeights = [Int: CGFloat]()
- public func height
- (item: Item, indexPath: NSIndexPath, cell: Cell.Type) -> CGFloat {
+ public func height(indexPath: NSIndexPath, reusableIdentifier: String, configure: (cell: UITableViewCell) -> Void) -> CGFloat {
- guard let cell = tableView?.dequeueReusableCellWithIdentifier(Cell.reusableIdentifier()) as? Cell else { return 0 }
+ guard let cell = tableView?.dequeueReusableCellWithIdentifier(reusableIdentifier) else { return 0 }
cell.bounds = CGRectMake(0, 0, tableView?.bounds.size.width ?? 0, cell.bounds.height)
- cell.configure(item)
+ configure(cell: cell)
cell.setNeedsLayout()
cell.layoutIfNeeded()
diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift
index 03545f6..3e8075f 100644
--- a/Sources/TableDirector.swift
+++ b/Sources/TableDirector.swift
@@ -28,6 +28,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
public private(set) weak var tableView: UITableView?
public private(set) var sections = [TableSection]()
private weak var scrollDelegate: UIScrollViewDelegate?
+ private var heightStrategy: HeightCalculatingStrategy?
public init(tableView: UITableView, scrollDelegate: UIScrollViewDelegate? = nil) {
super.init()
@@ -81,7 +82,12 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
}
public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
- return sections[indexPath.section].items[indexPath.row].defaultHeight
+
+ let row = sections[indexPath.section].items[indexPath.row]
+
+ return heightStrategy?.height(indexPath, reusableIdentifier: row.reusableIdentifier, configure: { (cell) in
+ row.configure(cell)
+ }) ?? sections[indexPath.section].items[indexPath.row].defaultHeight
}
// MARK: UITableViewDataSource - configuration
diff --git a/Sources/TableRow.swift b/Sources/TableRow.swift
index 2b06615..62fd90b 100644
--- a/Sources/TableRow.swift
+++ b/Sources/TableRow.swift
@@ -60,7 +60,7 @@ public class TableRow
Date: Tue, 14 Jun 2016 23:50:30 +0300
Subject: [PATCH 06/29] add RowHashable protocol
---
.../Presentation/Controllers/MainController.swift | 4 +---
Sources/HeightStrategy.swift | 2 +-
Sources/TableRow.swift | 11 ++++++++++-
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift
index bec8ab6..91b855d 100644
--- a/Demo/Classes/Presentation/Controllers/MainController.swift
+++ b/Demo/Classes/Presentation/Controllers/MainController.swift
@@ -35,9 +35,7 @@ class MainController: UIViewController {
let row1 = TableRow(item: "1")
let row2 = TableRow(item: "2")
let row3 = TableRow(item: "3", actions: [a])
-
-
-
+
row1
.addAction(TableRowAction(.shouldHighlight) { (data) -> Bool in
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index 9072767..72eef2e 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -27,7 +27,7 @@ public protocol HeightCalculatingStrategy {
func height(indexPath: NSIndexPath, reusableIdentifier: String, configure: (cell: UITableViewCell) -> Void) -> CGFloat
}
-public class PrototypeHeightStrategy {
+public class PrototypeHeightStrategy: HeightCalculatingStrategy {
public weak var tableView: UITableView?
private var cachedHeights = [Int: CGFloat]()
diff --git a/Sources/TableRow.swift b/Sources/TableRow.swift
index 62fd90b..e4b3fbb 100644
--- a/Sources/TableRow.swift
+++ b/Sources/TableRow.swift
@@ -31,7 +31,12 @@ public protocol RowActionable {
func hasAction(action: TableRowActionType) -> Bool
}
-public protocol Row: RowConfigurable, RowActionable {
+public protocol RowHashable {
+
+ var hashValue: Int { get }
+}
+
+public protocol Row: RowConfigurable, RowActionable, RowHashable {
var reusableIdentifier: String { get }
var estimatedHeight: CGFloat { get }
@@ -42,6 +47,10 @@ public class TableRow]()
+
+ public var hashValue: Int {
+ return ObjectIdentifier(self).hashValue
+ }
public var reusableIdentifier: String {
return CellType.reusableIdentifier()
From 9d0c278a347d1b1daa43767772b6e18d8728b9a8 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Wed, 15 Jun 2016 01:05:04 +0300
Subject: [PATCH 07/29] add shouldUsePrototypeCellHeightCalculation property
---
.../Controllers/MainController.swift | 1 +
.../Views/StoryboardImageTableViewCell.swift | 4 +--
Sources/HeightStrategy.swift | 33 ++++++++++++++-----
Sources/TableDirector.swift | 20 +++++++----
4 files changed, 42 insertions(+), 16 deletions(-)
diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift
index 91b855d..4cc8203 100644
--- a/Demo/Classes/Presentation/Controllers/MainController.swift
+++ b/Demo/Classes/Presentation/Controllers/MainController.swift
@@ -14,6 +14,7 @@ class MainController: UIViewController {
@IBOutlet weak var tableView: UITableView! {
didSet {
tableDirector = TableDirector(tableView: tableView)
+ tableDirector.shouldUsePrototypeCellHeightCalculation = true
}
}
var tableDirector: TableDirector!
diff --git a/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift b/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift
index 4cd5631..a466f9a 100644
--- a/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift
+++ b/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift
@@ -30,7 +30,7 @@ class StoryboardImageTableViewCell: UITableViewCell, ConfigurableCell {
override func layoutSubviews() {
super.layoutSubviews()
- //contentView.layoutIfNeeded()
- //subtitleLabel.preferredMaxLayoutWidth = subtitleLabel.bounds.size.width
+ contentView.layoutIfNeeded()
+ subtitleLabel.preferredMaxLayoutWidth = subtitleLabel.bounds.size.width
}
}
\ No newline at end of file
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index 72eef2e..469542e 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -20,29 +20,46 @@
import UIKit
-public protocol HeightCalculatingStrategy {
+public protocol CellHeightCalculatable {
var tableView: UITableView? { get set }
- func height(indexPath: NSIndexPath, reusableIdentifier: String, configure: (cell: UITableViewCell) -> Void) -> CGFloat
+ func height(row: Row, path: NSIndexPath) -> CGFloat
+ func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat
}
-public class PrototypeHeightStrategy: HeightCalculatingStrategy {
+public class PrototypeHeightStrategy: CellHeightCalculatable {
public weak var tableView: UITableView?
private var cachedHeights = [Int: CGFloat]()
- public func height(indexPath: NSIndexPath, reusableIdentifier: String, configure: (cell: UITableViewCell) -> Void) -> CGFloat {
+ init(tableView: UITableView?) {
+ self.tableView = tableView
+ }
+
+ public func height(row: Row, path: NSIndexPath) -> CGFloat {
- guard let cell = tableView?.dequeueReusableCellWithIdentifier(reusableIdentifier) else { return 0 }
+ if let height = cachedHeights[row.hashValue] {
+ return height
+ }
+
+ guard let cell = tableView?.dequeueReusableCellWithIdentifier(row.reusableIdentifier) else { return 0 }
cell.bounds = CGRectMake(0, 0, tableView?.bounds.size.width ?? 0, cell.bounds.height)
-
- configure(cell: cell)
+
+ row.configure(cell)
cell.setNeedsLayout()
cell.layoutIfNeeded()
- return cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
+ let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
+
+ cachedHeights[row.hashValue] = height
+
+ return height
+ }
+
+ public func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat {
+ return UITableViewAutomaticDimension
}
}
\ No newline at end of file
diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift
index 3e8075f..42f018c 100644
--- a/Sources/TableDirector.swift
+++ b/Sources/TableDirector.swift
@@ -27,8 +27,17 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
public private(set) weak var tableView: UITableView?
public private(set) var sections = [TableSection]()
+
private weak var scrollDelegate: UIScrollViewDelegate?
- private var heightStrategy: HeightCalculatingStrategy?
+ private var heightStrategy: CellHeightCalculatable?
+
+ public var shouldUsePrototypeCellHeightCalculation: Bool = false {
+ didSet {
+ if shouldUsePrototypeCellHeightCalculation {
+ heightStrategy = PrototypeHeightStrategy(tableView: tableView)
+ }
+ }
+ }
public init(tableView: UITableView, scrollDelegate: UIScrollViewDelegate? = nil) {
super.init()
@@ -78,16 +87,15 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
// MARK: - Height
public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
- return sections[indexPath.section].items[indexPath.row].estimatedHeight
+
+ let row = sections[indexPath.section].items[indexPath.row]
+ return heightStrategy?.estimatedHeight(row, path: indexPath) ?? row.estimatedHeight
}
public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let row = sections[indexPath.section].items[indexPath.row]
-
- return heightStrategy?.height(indexPath, reusableIdentifier: row.reusableIdentifier, configure: { (cell) in
- row.configure(cell)
- }) ?? sections[indexPath.section].items[indexPath.row].defaultHeight
+ return heightStrategy?.height(row, path: indexPath) ?? row.defaultHeight
}
// MARK: UITableViewDataSource - configuration
From 98c481be71c12682ecf341968cb6ae64f39f96f2 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Wed, 15 Jun 2016 01:21:12 +0300
Subject: [PATCH 08/29] handle separator height
---
Demo/Classes/Presentation/Controllers/MainController.swift | 3 +--
README.md | 2 +-
Sources/HeightStrategy.swift | 5 +++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift
index 4cc8203..e8812d1 100644
--- a/Demo/Classes/Presentation/Controllers/MainController.swift
+++ b/Demo/Classes/Presentation/Controllers/MainController.swift
@@ -21,8 +21,7 @@ class MainController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
-
-
+
let a = TableRowAction(.click) {
(data) in
diff --git a/README.md b/README.md
index 170adf3..0f02666 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ It hides a complexity of `UITableViewDataSource` and `UITableViewDelegate` metho
- [x] Correctly handles autolayout cells with multiline labels
- [x] Chainable cell actions (select/deselect etc.)
- [x] Support cells created from code, xib, or storyboard
-- [x] Automatic xib/classes registration
+- [x] Support different cells height calculation strategies
- [x] No need to subclass
- [x] Extensibility
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index 469542e..43243ff 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -32,6 +32,7 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
public weak var tableView: UITableView?
private var cachedHeights = [Int: CGFloat]()
+ private var separatorHeight = 1 / UIScreen.mainScreen().scale
init(tableView: UITableView?) {
self.tableView = tableView
@@ -51,8 +52,8 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
cell.setNeedsLayout()
cell.layoutIfNeeded()
-
- let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1
+
+ let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + (tableView?.separatorStyle != .None ? separatorHeight : 0)
cachedHeights[row.hashValue] = height
From a2f8bdde307b91a77f429ef6619017c1bd539ef2 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Wed, 15 Jun 2016 20:42:10 +0300
Subject: [PATCH 09/29] add isPrototype property
---
.../Presentation/Views/StoryboardImageTableViewCell.swift | 2 +-
.../Presentation/Views/StoryboardTableViewCell.swift | 2 +-
Sources/ConfigurableCell.swift | 2 +-
Sources/HeightStrategy.swift | 2 +-
Sources/TableDirector.swift | 2 +-
Sources/TableRow.swift | 6 +++---
6 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift b/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift
index a466f9a..6d0df90 100644
--- a/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift
+++ b/Demo/Classes/Presentation/Views/StoryboardImageTableViewCell.swift
@@ -17,7 +17,7 @@ class StoryboardImageTableViewCell: UITableViewCell, ConfigurableCell {
@IBOutlet var subtitleLabel: UILabel!
@IBOutlet var customImageView: UIImageView!
- func configure(string: T) {
+ func configure(string: T, isPrototype: Bool) {
titleLabel.text = string
subtitleLabel.text = "Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.Copyright © 2016 Tablet. All rights reserved.1"
diff --git a/Demo/Classes/Presentation/Views/StoryboardTableViewCell.swift b/Demo/Classes/Presentation/Views/StoryboardTableViewCell.swift
index 8180860..a8b84c0 100644
--- a/Demo/Classes/Presentation/Views/StoryboardTableViewCell.swift
+++ b/Demo/Classes/Presentation/Views/StoryboardTableViewCell.swift
@@ -13,7 +13,7 @@ class StoryboardTableViewCell: UITableViewCell, ConfigurableCell {
typealias T = String
- func configure(value: T) {
+ func configure(value: T, isPrototype: Bool) {
textLabel?.text = value
}
}
\ No newline at end of file
diff --git a/Sources/ConfigurableCell.swift b/Sources/ConfigurableCell.swift
index 4127139..3e42f17 100644
--- a/Sources/ConfigurableCell.swift
+++ b/Sources/ConfigurableCell.swift
@@ -27,7 +27,7 @@ public protocol ConfigurableCell {
static func reusableIdentifier() -> String
static func estimatedHeight() -> CGFloat
static func defaultHeight() -> CGFloat?
- func configure(_: T)
+ func configure(_: T, isPrototype: Bool)
}
public extension ConfigurableCell where Self: UITableViewCell {
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index 43243ff..084018c 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -48,7 +48,7 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
cell.bounds = CGRectMake(0, 0, tableView?.bounds.size.width ?? 0, cell.bounds.height)
- row.configure(cell)
+ row.configure(cell, isPrototype: true)
cell.setNeedsLayout()
cell.layoutIfNeeded()
diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift
index 42f018c..72b8fb1 100644
--- a/Sources/TableDirector.swift
+++ b/Sources/TableDirector.swift
@@ -118,7 +118,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
cell.layoutIfNeeded()
}
- row.configure(cell)
+ row.configure(cell, isPrototype: false)
return cell
}
diff --git a/Sources/TableRow.swift b/Sources/TableRow.swift
index e4b3fbb..ff33a2e 100644
--- a/Sources/TableRow.swift
+++ b/Sources/TableRow.swift
@@ -22,7 +22,7 @@ import UIKit
public protocol RowConfigurable {
- func configure(cell: UITableViewCell)
+ func configure(cell: UITableViewCell, isPrototype: Bool)
}
public protocol RowActionable {
@@ -72,8 +72,8 @@ public class TableRow
Date: Wed, 15 Jun 2016 20:42:53 +0300
Subject: [PATCH 10/29] update readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 0f02666..3b56f80 100644
--- a/README.md
+++ b/README.md
@@ -46,7 +46,7 @@ class StringTableViewCell: UITableViewCell, ConfigurableCell {
typealias T = String
- func configure(string: T) {
+ func configure(string: T, isPrototype: Bool) {
titleLabel.text = string
}
From 1bd049e276042b72b3d434c62364843082b915ae Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Wed, 15 Jun 2016 20:56:17 +0300
Subject: [PATCH 11/29] add delete and insert methods
---
.../Controllers/MainController.swift | 41 -------------------
Sources/TableSection.swift | 10 ++++-
2 files changed, 9 insertions(+), 42 deletions(-)
diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift
index e8812d1..3569741 100644
--- a/Demo/Classes/Presentation/Controllers/MainController.swift
+++ b/Demo/Classes/Presentation/Controllers/MainController.swift
@@ -46,52 +46,11 @@ class MainController: UIViewController {
.addAction(TableRowAction(.click) { (data) in
print("2")
-
-
})
-
let section = TableSection()
section.append(builder: b)
- //let section = TableSection(headerTitle: "", footerTitle: "", rows: [row1, row2, row3])
-
tableDirector += [section]
-
- //tableDirector.append(section: section)
-
-
-
-
-
-
- /*rowBuilder
- .addAction(TableRowAction(type: .Click) { (data) in
-
-
- })
-
- rowBuilder
- .delete(indexes: [0], animated: .None)
- .insert(["2"], atIndex: 0, animated: .None)
- .update(index: 0, item: "", animated: .None)
- .move([1, 2], toIndexes: [3, 4])
-
-
-
- //tableView.moveRowAtIndexPath(<#T##indexPath: NSIndexPath##NSIndexPath#>, toIndexPath: <#T##NSIndexPath#>)
- //tableView.deleteRowsAtIndexPaths(<#T##indexPaths: [NSIndexPath]##[NSIndexPath]#>, withRowAnimation: <#T##UITableViewRowAnimation#>)
- //tableView.insertRowsAtIndexPaths(<#T##indexPaths: [NSIndexPath]##[NSIndexPath]#>, withRowAnimation: <#T##UITableViewRowAnimation#>)
- //tableView.reloadRowsAtIndexPaths(<#T##indexPaths: [NSIndexPath]##[NSIndexPath]#>, withRowAnimation: <#T##UITableViewRowAnimation#>)
-
- //tableView.moveSection(0, toSection: 0)
- //tableView.reloadSections([], withRowAnimation: .None)
- //tableView.deleteSections([], withRowAnimation: .None)
- //tableView.insertSections([], withRowAnimation: .None)
-
- //tableDirector.performBatchUpdates {
- //}*/
-
- //tableDirector.append(section: section)
}
}
\ No newline at end of file
diff --git a/Sources/TableSection.swift b/Sources/TableSection.swift
index 71fe404..e09078e 100644
--- a/Sources/TableSection.swift
+++ b/Sources/TableSection.swift
@@ -66,8 +66,16 @@ public class TableSection {
public func append(row row: Row) {
append(rows: [row])
}
-
+
public func append(rows rows: [Row]) {
items.appendContentsOf(rows)
}
+
+ public func insert(row row: Row, atIndex index: Int) {
+ items.insert(row, atIndex: index)
+ }
+
+ public func delete(index: Int) {
+ items.removeAtIndex(index)
+ }
}
\ No newline at end of file
From dd78ffa41e8b1ef18e21aa9e1d5b2435f65dada2 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Wed, 15 Jun 2016 21:13:34 +0300
Subject: [PATCH 12/29] rowItems -> rows
---
Sources/TableRowBuilder.swift | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Sources/TableRowBuilder.swift b/Sources/TableRowBuilder.swift
index 4b37799..23158c2 100644
--- a/Sources/TableRowBuilder.swift
+++ b/Sources/TableRowBuilder.swift
@@ -22,7 +22,7 @@ import UIKit
public protocol RowBuilder {
- func rowItems() -> [Row]?
+ func rows() -> [Row]?
}
public class TableRowBuilder: RowBuilder {
@@ -42,7 +42,7 @@ public class TableRowBuilder [Row]? {
+ public func rows() -> [Row]? {
return items?.map { TableRow(item: $0, actions: actions) }
}
}
@@ -51,7 +51,7 @@ public extension TableSection {
public func append(builder builder: RowBuilder) {
- if let rows = builder.rowItems() {
+ if let rows = builder.rows() {
append(rows: rows)
}
}
From 23378e2de40b376c8216f3ae6c0d3e40c98da1ef Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Wed, 15 Jun 2016 21:23:41 +0300
Subject: [PATCH 13/29] add invalidate
---
Sources/HeightStrategy.swift | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index 084018c..f873906 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -26,6 +26,8 @@ public protocol CellHeightCalculatable {
func height(row: Row, path: NSIndexPath) -> CGFloat
func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat
+
+ func invalidate()
}
public class PrototypeHeightStrategy: CellHeightCalculatable {
@@ -63,4 +65,8 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
public func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
+
+ public func invalidate() {
+ cachedHeights.removeAll()
+ }
}
\ No newline at end of file
From 09e5c4b8a44497c71e19abd8e923d2d57464a9e8 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Wed, 15 Jun 2016 21:25:28 +0300
Subject: [PATCH 14/29] update readme
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 3b56f80..9e100ea 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,7 @@ It hides a complexity of `UITableViewDataSource` and `UITableViewDelegate` metho
- [x] Chainable cell actions (select/deselect etc.)
- [x] Support cells created from code, xib, or storyboard
- [x] Support different cells height calculation strategies
+- [x] Support portrait and landscape orientations
- [x] No need to subclass
- [x] Extensibility
From 03b67c51783a573734f2b62d7318450e1aea7c51 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Thu, 16 Jun 2016 00:54:22 +0300
Subject: [PATCH 15/29] update readme
---
README.md | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 9e100ea..1055f80 100644
--- a/README.md
+++ b/README.md
@@ -26,6 +26,10 @@ It hides a complexity of `UITableViewDataSource` and `UITableViewDelegate` metho
## Getting Started
+An example app is included demonstrating TableKit's functionality.
+
+#### Basic usage
+
Create your rows:
```swift
let row1 = TableRow(item: "1")
@@ -58,7 +62,9 @@ class StringTableViewCell: UITableViewCell, ConfigurableCell {
```
You could have as many rows and sections as you need.
-## Row actions
+## Advanced
+
+#### Row actions
It nice to have some actions that related to your cells:
```swift
@@ -85,7 +91,7 @@ row
})
```
-## Batch rows
+#### Batch rows
You could have a situation when you need a lot of cells with the same type. In that case it's better to use `TableRowBuilder`:
```swift
let builder = TableRowBuilder {
From 018c35ef5317614b8e00ff260fd4b2102ce40100 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Thu, 16 Jun 2016 01:16:53 +0300
Subject: [PATCH 16/29] update readme
---
README.md | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/README.md b/README.md
index 1055f80..2933cde 100644
--- a/README.md
+++ b/README.md
@@ -71,6 +71,7 @@ It nice to have some actions that related to your cells:
let action = TableRowAction(.click) { (data) in
// you could access any useful information that relates to the action
+
// data.cell - StringTableViewCell?
// data.item - String
// data.path - NSIndexPath
@@ -90,6 +91,7 @@ row
return false
})
```
+You could find all available actions here.
#### Batch rows
You could have a situation when you need a lot of cells with the same type. In that case it's better to use `TableRowBuilder`:
@@ -110,6 +112,37 @@ let builder = TableRowBuilder(items: ["1", "2", "3"
section.append(builder: builder)
```
+#### Cell height calculating strategy
+By default TableKit relies on self-sizing cells. In that case you have to provide an estimated height for your cells:
+```swift
+class StringTableViewCell: UITableViewCell, ConfigurableCell {
+
+ // ...
+
+ static func estimatedHeight() -> CGFloat {
+ return 44
+ }
+}
+```
+It's enough for most cases. But you may not be happy with this. So you could use
+```swift
+tableDirector.shouldUsePrototypeCellHeightCalculation = true
+```
+It does all dirty work with prototypes behind the scene, so you don't have to worry about anything except of your cell configuration:
+```swift
+class ImageTableViewCell: UITableViewCell, ConfigurableCell {
+
+ func configure(url: NSURL, isPrototype: Bool) {
+
+ if !isPrototype {
+ loadImageAsync(url: url, imageView: imageView)
+ }
+ }
+}
+```
+As you can see you don't have to load any remote images to your cell, cause it's not visible. It's a prototype cell, just to calculate apropriate height.
+
+
## Installation
#### CocoaPods
From 0d7d97db57c09b5b34d82a233c0eeed8c97f419d Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Thu, 16 Jun 2016 01:42:24 +0300
Subject: [PATCH 17/29] update readme
---
README.md | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 2933cde..71eae3a 100644
--- a/README.md
+++ b/README.md
@@ -124,11 +124,11 @@ class StringTableViewCell: UITableViewCell, ConfigurableCell {
}
}
```
-It's enough for most cases. But you may not be happy with this. So you could use
+It's enough for most cases. But you may be not happy with this. So you could use a prototype cell to calculate cell's heights. To enable this feature simply use this property:
```swift
tableDirector.shouldUsePrototypeCellHeightCalculation = true
```
-It does all dirty work with prototypes behind the scene, so you don't have to worry about anything except of your cell configuration:
+It does all dirty work with prototypes for you behind the scene, so you don't have to worry about anything except of your cell configuration:
```swift
class ImageTableViewCell: UITableViewCell, ConfigurableCell {
@@ -138,10 +138,16 @@ class ImageTableViewCell: UITableViewCell, ConfigurableCell {
loadImageAsync(url: url, imageView: imageView)
}
}
+
+ override func layoutSubviews() {
+ super.layoutSubviews()
+
+ contentView.layoutIfNeeded()
+ multilineLabel.preferredMaxLayoutWidth = multilineLabel.bounds.size.width
+ }
}
```
-As you can see you don't have to load any remote images to your cell, cause it's not visible. It's a prototype cell, just to calculate apropriate height.
-
+First of all you have to set `preferredMaxLayoutWidth` for all your multiline labels. And check if a configuring cell is a prototype cell. If it is, you don't have to do any additional work that not actually affect cell's height. For example you don't have to load remote image for a prototype cell.
## Installation
From d4efb6a679665f9a899a13fe5a9949a459e9f853 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Thu, 16 Jun 2016 22:45:33 +0300
Subject: [PATCH 18/29] improve hash
---
Sources/HeightStrategy.swift | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index f873906..f6a5ad6 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -41,23 +41,27 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
}
public func height(row: Row, path: NSIndexPath) -> CGFloat {
-
- if let height = cachedHeights[row.hashValue] {
+
+ guard let tableView = tableView else { return 0 }
+
+ let hash = row.hashValue ^ Int(tableView.bounds.size.width).hashValue
+
+ if let height = cachedHeights[hash] {
return height
}
- guard let cell = tableView?.dequeueReusableCellWithIdentifier(row.reusableIdentifier) else { return 0 }
-
- cell.bounds = CGRectMake(0, 0, tableView?.bounds.size.width ?? 0, cell.bounds.height)
+ guard let cell = tableView.dequeueReusableCellWithIdentifier(row.reusableIdentifier) else { return 0 }
+
+ cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height)
row.configure(cell, isPrototype: true)
-
+
cell.setNeedsLayout()
cell.layoutIfNeeded()
- let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + (tableView?.separatorStyle != .None ? separatorHeight : 0)
+ let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + (tableView.separatorStyle != .None ? separatorHeight : 0)
- cachedHeights[row.hashValue] = height
+ cachedHeights[hash] = height
return height
}
From 1266a9144649a396e273fd2dd91f9f2e48244b56 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Thu, 16 Jun 2016 23:59:25 +0300
Subject: [PATCH 19/29] addAction -> action
---
.../Presentation/Controllers/MainController.swift | 4 ++--
Demo/Resources/Storyboards/LaunchScreen.storyboard | 2 +-
Demo/Resources/Storyboards/Main.storyboard | 12 ++++++------
README.md | 6 ++----
Sources/HeightStrategy.swift | 1 +
Sources/TableRow.swift | 2 +-
6 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/Demo/Classes/Presentation/Controllers/MainController.swift b/Demo/Classes/Presentation/Controllers/MainController.swift
index 3569741..a9694cb 100644
--- a/Demo/Classes/Presentation/Controllers/MainController.swift
+++ b/Demo/Classes/Presentation/Controllers/MainController.swift
@@ -37,13 +37,13 @@ class MainController: UIViewController {
let row3 = TableRow(item: "3", actions: [a])
row1
- .addAction(TableRowAction(.shouldHighlight) { (data) -> Bool in
+ .action(TableRowAction(.shouldHighlight) { (data) -> Bool in
print("1")
return false
})
- .addAction(TableRowAction(.click) { (data) in
+ .action(TableRowAction(.click) { (data) in
print("2")
})
diff --git a/Demo/Resources/Storyboards/LaunchScreen.storyboard b/Demo/Resources/Storyboards/LaunchScreen.storyboard
index 0a546bb..580ceb8 100644
--- a/Demo/Resources/Storyboards/LaunchScreen.storyboard
+++ b/Demo/Resources/Storyboards/LaunchScreen.storyboard
@@ -1,5 +1,5 @@
-
+
diff --git a/Demo/Resources/Storyboards/Main.storyboard b/Demo/Resources/Storyboards/Main.storyboard
index 4edf1ae..4d18da9 100644
--- a/Demo/Resources/Storyboards/Main.storyboard
+++ b/Demo/Resources/Storyboards/Main.storyboard
@@ -1,5 +1,5 @@
-
+
@@ -26,7 +26,7 @@
-
+
@@ -39,7 +39,7 @@
-
+
@@ -85,7 +85,7 @@
-
+
@@ -117,7 +117,7 @@
-
+
@@ -130,7 +130,7 @@
-
+
diff --git a/README.md b/README.md
index 71eae3a..439f178 100644
--- a/README.md
+++ b/README.md
@@ -82,12 +82,10 @@ let row = TableRow(item: "some", actions: [action])
Or, using nice chaining approach:
```swift
let row = TableRow(item: "some")
-
-row
- .addAction(TableRowAction(.click) { (data) in
+ .action(TableRowAction(.click) { (data) in
})
- .addAction(TableRowAction(.shouldHighlight) { (data) -> Bool in
+ .action(TableRowAction(.shouldHighlight) { (data) -> Bool in
return false
})
```
diff --git a/Sources/HeightStrategy.swift b/Sources/HeightStrategy.swift
index f6a5ad6..c6e7d25 100644
--- a/Sources/HeightStrategy.swift
+++ b/Sources/HeightStrategy.swift
@@ -33,6 +33,7 @@ public protocol CellHeightCalculatable {
public class PrototypeHeightStrategy: CellHeightCalculatable {
public weak var tableView: UITableView?
+ private var prototypes = [String: UITableViewCell]()
private var cachedHeights = [Int: CGFloat]()
private var separatorHeight = 1 / UIScreen.mainScreen().scale
diff --git a/Sources/TableRow.swift b/Sources/TableRow.swift
index ff33a2e..3dac46b 100644
--- a/Sources/TableRow.swift
+++ b/Sources/TableRow.swift
@@ -88,7 +88,7 @@ public class TableRow) -> Self {
+ public func action(action: TableRowAction) -> Self {
actions[action.type.key] = action
return self
From 86b93ae78d5906a8f5796ae44069f40d04901d26 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Fri, 17 Jun 2016 00:01:55 +0300
Subject: [PATCH 20/29] update readme
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 439f178..1e4259f 100644
--- a/README.md
+++ b/README.md
@@ -62,8 +62,6 @@ class StringTableViewCell: UITableViewCell, ConfigurableCell {
```
You could have as many rows and sections as you need.
-## Advanced
-
#### Row actions
It nice to have some actions that related to your cells:
@@ -110,6 +108,8 @@ let builder = TableRowBuilder(items: ["1", "2", "3"
section.append(builder: builder)
```
+## Advanced
+
#### Cell height calculating strategy
By default TableKit relies on self-sizing cells. In that case you have to provide an estimated height for your cells:
```swift
From 1bc7301c7e090664f7a739f48c8c8ee6ba73b796 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 04:17:58 +0300
Subject: [PATCH 21/29] add operators
---
README.md | 2 +-
Sources/Operators.swift | 9 +++++++++
Tests/TableKitTests.swift | 28 ++++++++++++++++++++++------
3 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 1e4259f..6700590 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ It hides a complexity of `UITableViewDataSource` and `UITableViewDelegate` metho
## Features
-- [x] Type-safe cells based on generics
+- [x] Type-safe generic cells
- [x] The easiest way to map your models or view models to cells
- [x] Correctly handles autolayout cells with multiline labels
- [x] Chainable cell actions (select/deselect etc.)
diff --git a/Sources/Operators.swift b/Sources/Operators.swift
index 14a4326..3f0f555 100644
--- a/Sources/Operators.swift
+++ b/Sources/Operators.swift
@@ -27,6 +27,15 @@ public func +=(left: TableDirector, right: [TableSection]) {
left.append(sections: right)
}
+// --
+public func +=(left: TableDirector, right: Row) {
+ left.append(sections: [TableSection(rows: [right])])
+}
+
+public func +=(left: TableDirector, right: [Row]) {
+ left.append(sections: [TableSection(rows: right)])
+}
+
// --
public func +=(left: TableSection, right: Row) {
left.append(row: right)
diff --git a/Tests/TableKitTests.swift b/Tests/TableKitTests.swift
index 868e288..2a26050 100644
--- a/Tests/TableKitTests.swift
+++ b/Tests/TableKitTests.swift
@@ -45,7 +45,7 @@ struct TestTableViewCellOptions {
static let EstimatedHeight: Float = 255
}
-/*class TestTableViewCell: UITableViewCell, ConfigurableCell {
+class TestTableViewCell: UITableViewCell, ConfigurableCell {
typealias T = TestData
@@ -57,12 +57,12 @@ struct TestTableViewCellOptions {
return TestTableViewCellOptions.EstimatedHeight
}
- func configure(item: T) {
+ func configure(item: T, isPrototype: Bool) {
textLabel?.text = item.title
}
func raiseAction() {
- Action(key: TestTableViewCellOptions.CellAction, sender: self, userInfo: [TestTableViewCellOptions.CellActionUserInfoKey: TestTableViewCellOptions.CellActionUserInfoValue]).invoke()
+ //Action(key: TestTableViewCellOptions.CellAction, sender: self, userInfo: [TestTableViewCellOptions.CellActionUserInfoKey: TestTableViewCellOptions.CellActionUserInfoValue]).invoke()
}
}
@@ -74,6 +74,7 @@ class TabletTests: XCTestCase {
super.setUp()
testController = TestController()
+ let _ = testController.view
}
override func tearDown() {
@@ -89,7 +90,22 @@ class TabletTests: XCTestCase {
XCTAssertNotNil(testController.tableDirector.tableView, "TableDirector should have table view")
}
- func testSimpleRowBuilderCreatesRowsAndSection() {
+ func testRow() {
+
+ let data = TestData(title: "title")
+
+ let row = TableRow(item: data)
+
+ testController.tableDirector += row
+
+ XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
+ XCTAssertTrue(testController.tableView.dataSource?.tableView(testController.tableView, numberOfRowsInSection: 0) == 1, "Table view should have certain number of rows in a section")
+
+ let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as? TestTableViewCell
+ XCTAssertNotNil(cell)
+ }
+
+ /*func testSimpleRowBuilderCreatesRowsAndSection() {
let source = ["1", "2", "3"]
@@ -196,5 +212,5 @@ class TabletTests: XCTestCase {
cell?.raiseAction()
waitForExpectationsWithTimeout(1.0, handler: nil)
- }
-}*/
\ No newline at end of file
+ }*/
+}
\ No newline at end of file
From 23cceddfe2e256de54935ee26cdf7d9891c6b849 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 04:31:19 +0300
Subject: [PATCH 22/29] functional programming example
---
README.md | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/README.md b/README.md
index 6700590..a86fc2c 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ It hides a complexity of `UITableViewDataSource` and `UITableViewDelegate` metho
## Features
- [x] Type-safe generic cells
+- [x] Functional programming style friendly
- [x] The easiest way to map your models or view models to cells
- [x] Correctly handles autolayout cells with multiline labels
- [x] Chainable cell actions (select/deselect etc.)
@@ -147,6 +148,15 @@ class ImageTableViewCell: UITableViewCell, ConfigurableCell {
```
First of all you have to set `preferredMaxLayoutWidth` for all your multiline labels. And check if a configuring cell is a prototype cell. If it is, you don't have to do any additional work that not actually affect cell's height. For example you don't have to load remote image for a prototype cell.
+#### Functional programming
+It's never been so easy to deal with table views.
+```swift
+let users = /* some users array */
+
+tableDirector += users.filter({ $0.state == .active }).map({ TableRow(item: $0.username) })
+```
+Done, your table is ready. It's just awesome!
+
## Installation
#### CocoaPods
From 221efc00abc4779fc5aa0f11ec89abef3c681c1e Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 05:42:49 +0300
Subject: [PATCH 23/29] add register cell method
---
README.md | 1 +
Sources/ConfigurableCell.swift | 20 ++++++++++++++++----
Sources/TableDirector.swift | 15 +++++++++++++++
Tests/TableKitTests.swift | 1 +
4 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index a86fc2c..4f053bd 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,7 @@ let section = TableSection(rows: [row1, row2, row3])
And setup your table:
```swift
let tableDirector = TableDirector(tableView: tableView)
+tableDirector.register(StringTableViewCell.self, IntTableViewCell.self, FloatTableViewCell.self)
tableDirector += section
```
Done. Your table is ready. You may want to look at your cell. It has to conform to `ConfigurableCell` protocol:
diff --git a/Sources/ConfigurableCell.swift b/Sources/ConfigurableCell.swift
index 3e42f17..473f7cc 100644
--- a/Sources/ConfigurableCell.swift
+++ b/Sources/ConfigurableCell.swift
@@ -20,21 +20,33 @@
import UIKit
-public protocol ConfigurableCell {
+public protocol ReusableCell {
+
+ static func reusableIdentifier() -> String
+ static func nib() -> UINib?
+}
+
+public protocol ConfigurableCell: ReusableCell {
associatedtype T
- static func reusableIdentifier() -> String
static func estimatedHeight() -> CGFloat
static func defaultHeight() -> CGFloat?
func configure(_: T, isPrototype: Bool)
}
-public extension ConfigurableCell where Self: UITableViewCell {
-
+public extension ReusableCell where Self: UITableViewCell {
+
static func reusableIdentifier() -> String {
return String(self)
}
+
+ static func nib() -> UINib? {
+ return nil
+ }
+}
+
+public extension ConfigurableCell where Self: UITableViewCell {
static func estimatedHeight() -> CGFloat {
return UITableViewAutomaticDimension
diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift
index 72b8fb1..3d67049 100644
--- a/Sources/TableDirector.swift
+++ b/Sources/TableDirector.swift
@@ -57,6 +57,21 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
public func reload() {
tableView?.reloadData()
}
+
+ public func register(cells: T.Type...) {
+
+ for cell in cells {
+ if let nib = cell.nib() {
+ tableView?.registerNib(nib, forCellReuseIdentifier: cell.reusableIdentifier())
+ } else {
+ if let nib = NSBundle(forClass: cell).loadNibNamed(cell.reusableIdentifier(), owner: nil, options: nil).first as? UINib {
+ tableView?.registerNib(nib, forCellReuseIdentifier: cell.reusableIdentifier())
+ } else {
+ tableView?.registerClass(cell, forCellReuseIdentifier: cell.reusableIdentifier())
+ }
+ }
+ }
+ }
// MARK: Public
diff --git a/Tests/TableKitTests.swift b/Tests/TableKitTests.swift
index 2a26050..bb2d8f8 100644
--- a/Tests/TableKitTests.swift
+++ b/Tests/TableKitTests.swift
@@ -28,6 +28,7 @@ class TestController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableDirector = TableDirector(tableView: tableView)
+ tableDirector.register([TestTableViewCell.self])
}
}
From dd6092f87fed92657379171e9b1d72644fccd18e Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 06:03:29 +0300
Subject: [PATCH 24/29] fix register cells
---
Sources/TableDirector.swift | 17 +++++++++++++----
Tests/TableKitTests.swift | 32 +++++++++++++++++++++++++++++---
2 files changed, 42 insertions(+), 7 deletions(-)
diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift
index 3d67049..170e06d 100644
--- a/Sources/TableDirector.swift
+++ b/Sources/TableDirector.swift
@@ -61,15 +61,24 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
public func register(cells: T.Type...) {
for cell in cells {
+
if let nib = cell.nib() {
+
tableView?.registerNib(nib, forCellReuseIdentifier: cell.reusableIdentifier())
+ return
+
} else {
- if let nib = NSBundle(forClass: cell).loadNibNamed(cell.reusableIdentifier(), owner: nil, options: nil).first as? UINib {
- tableView?.registerNib(nib, forCellReuseIdentifier: cell.reusableIdentifier())
- } else {
- tableView?.registerClass(cell, forCellReuseIdentifier: cell.reusableIdentifier())
+
+ let resource = cell.reusableIdentifier()
+ let bundle = NSBundle(forClass: cell)
+
+ if let _ = bundle.pathForResource(resource, ofType: "nib") {
+ tableView?.registerNib(UINib(nibName: resource, bundle: bundle), forCellReuseIdentifier: cell.reusableIdentifier())
+ return
}
}
+
+ tableView?.registerClass(cell, forCellReuseIdentifier: cell.reusableIdentifier())
}
}
diff --git a/Tests/TableKitTests.swift b/Tests/TableKitTests.swift
index bb2d8f8..a3e3ea3 100644
--- a/Tests/TableKitTests.swift
+++ b/Tests/TableKitTests.swift
@@ -28,7 +28,7 @@ class TestController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableDirector = TableDirector(tableView: tableView)
- tableDirector.register([TestTableViewCell.self])
+ tableDirector.register(TestTableViewCell.self)
}
}
@@ -75,7 +75,7 @@ class TabletTests: XCTestCase {
super.setUp()
testController = TestController()
- let _ = testController.view
+ testController.view.hidden = false
}
override func tearDown() {
@@ -91,21 +91,47 @@ class TabletTests: XCTestCase {
XCTAssertNotNil(testController.tableDirector.tableView, "TableDirector should have table view")
}
- func testRow() {
+ func testRowInSection() {
let data = TestData(title: "title")
let row = TableRow(item: data)
testController.tableDirector += row
+ testController.tableView.reloadData()
XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
XCTAssertTrue(testController.tableView.dataSource?.tableView(testController.tableView, numberOfRowsInSection: 0) == 1, "Table view should have certain number of rows in a section")
let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as? TestTableViewCell
XCTAssertNotNil(cell)
+ XCTAssertTrue(cell?.textLabel?.text == data.title)
}
+ func testManyRowsInSection() {
+
+ let data = [TestData(title: "1"), TestData(title: "2"), TestData(title: "3")]
+
+ let rows: [TableRow] = data.map { TableRow(item: $0) }
+
+ testController.tableDirector += rows
+ testController.tableView.reloadData()
+
+ XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
+ XCTAssertTrue(testController.tableView.dataSource?.tableView(testController.tableView, numberOfRowsInSection: 0) == data.count, "Table view should have certain number of rows in a section")
+
+ for (index, element) in data.enumerate() {
+
+ let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0)) as? TestTableViewCell
+ XCTAssertNotNil(cell)
+ XCTAssertTrue(cell?.textLabel?.text == element.title)
+ }
+ }
+
+
+
+
+
/*func testSimpleRowBuilderCreatesRowsAndSection() {
let source = ["1", "2", "3"]
From 7e3d52fb92cb6294da9b92dbcb591889c6848d56 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 06:20:29 +0300
Subject: [PATCH 25/29] add tests
---
Sources/TableDirector.swift | 6 +++
Tests/TableKitTests.swift | 89 +++++++++----------------------------
2 files changed, 26 insertions(+), 69 deletions(-)
diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift
index 170e06d..5c1021c 100644
--- a/Sources/TableDirector.swift
+++ b/Sources/TableDirector.swift
@@ -223,6 +223,12 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
return self
}
+ public func append(rows rows: [Row]) -> Self {
+
+ append(section: TableSection(rows: rows))
+ return self
+ }
+
public func clear() -> Self {
sections.removeAll()
diff --git a/Tests/TableKitTests.swift b/Tests/TableKitTests.swift
index a3e3ea3..7a601e1 100644
--- a/Tests/TableKitTests.swift
+++ b/Tests/TableKitTests.swift
@@ -63,7 +63,7 @@ class TestTableViewCell: UITableViewCell, ConfigurableCell {
}
func raiseAction() {
- //Action(key: TestTableViewCellOptions.CellAction, sender: self, userInfo: [TestTableViewCellOptions.CellActionUserInfoKey: TestTableViewCellOptions.CellActionUserInfoValue]).invoke()
+ TableCellAction(key: TestTableViewCellOptions.CellAction, sender: self, userInfo: nil).invoke()
}
}
@@ -112,7 +112,7 @@ class TabletTests: XCTestCase {
let data = [TestData(title: "1"), TestData(title: "2"), TestData(title: "3")]
- let rows: [TableRow] = data.map { TableRow(item: $0) }
+ let rows: [Row] = data.map({ TableRow(item: $0) })
testController.tableDirector += rows
testController.tableView.reloadData()
@@ -128,64 +128,18 @@ class TabletTests: XCTestCase {
}
}
-
-
-
-
- /*func testSimpleRowBuilderCreatesRowsAndSection() {
-
- let source = ["1", "2", "3"]
-
- let rows = TableBaseRowBuilder(items: source)
- .action(.configure) { data -> Void in
-
- XCTAssertNotNil(data.cell, "Action should have a cell")
- data.cell?.textLabel?.text = "\(data.item)"
- }
+ func testTableSectionCreatesSectionWithHeaderAndFooterTitles() {
- testController.view.hidden = false
- testController.tableDirector += rows
- testController.tableView.reloadData()
-
- XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
- XCTAssertTrue(testController.tableView.dataSource?.tableView(testController.tableView, numberOfRowsInSection: 0) == source.count, "Table view should have certain number of rows in a section")
+ let row = TableRow(item: TestData(title: "title"))
- for (index, element) in source.enumerate() {
-
- let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0))
-
- XCTAssertNotNil(cell)
- XCTAssertTrue(cell?.textLabel?.text == element)
- }
- }
-
- func testConfigurableRowBuilderCreatesRowsAndSection() {
-
- let testData = TestData(title: "title")
-
- testController.view.hidden = false
- testController.tableDirector += TableRowBuilder(item: testData)
- testController.tableView.reloadData()
-
- let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as? TestTableViewCell
-
- XCTAssertNotNil(cell, "Cell should exists and should be TestTableViewCell")
- XCTAssertTrue(cell?.textLabel?.text == testData.title, "Cell's textLabel.text should equal to testData's title")
- }
-
- func testSectionBuilderCreatesSectionWithHeaderAndFooterTitles() {
-
- let row = TableRowBuilder(items: [TestData(title: "title")])
-
let sectionHeaderTitle = "Header Title"
let sectionFooterTitle = "Footer Title"
-
- let section = TableSectionBuilder(headerTitle: sectionHeaderTitle, footerTitle: sectionFooterTitle, rows: [row])
-
- testController.view.hidden = false
+
+ let section = TableSection(headerTitle: sectionHeaderTitle, footerTitle: sectionFooterTitle, rows: [row])
+
testController.tableDirector += section
testController.tableView.reloadData()
-
+
XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
XCTAssertTrue(testController.tableView.dataSource?.tableView(testController.tableView, numberOfRowsInSection: 0) == 1, "Table view should have certain number of rows in a section")
@@ -193,17 +147,16 @@ class TabletTests: XCTestCase {
XCTAssertTrue(testController.tableView.dataSource?.tableView?(testController.tableView, titleForFooterInSection: 0) == sectionFooterTitle)
}
- func testSectionBuilderCreatesSectionWithHeaderAndFooterViews() {
-
- let row = TableRowBuilder(items: [TestData(title: "title")])
+ func testTableSectionCreatesSectionWithHeaderAndFooterViews() {
+
+ let row = TableRow(item: TestData(title: "title"))
let sectionHeaderView = UIView()
let sectionFooterView = UIView()
-
- let section = TableSectionBuilder(headerView: sectionHeaderView, footerView: sectionFooterView, rows: nil)
+
+ let section = TableSection(headerView: sectionHeaderView, footerView: sectionFooterView, rows: nil)
section += row
- testController.view.hidden = false
testController.tableDirector += section
testController.tableView.reloadData()
@@ -213,20 +166,18 @@ class TabletTests: XCTestCase {
XCTAssertTrue(testController.tableView.delegate?.tableView?(testController.tableView, viewForHeaderInSection: 0) == sectionHeaderView)
XCTAssertTrue(testController.tableView.delegate?.tableView?(testController.tableView, viewForFooterInSection: 0) == sectionFooterView)
}
-
+
func testRowBuilderCustomActionInvokedAndSentUserInfo() {
let expectation = expectationWithDescription("cell action")
- let row = TableRowBuilder(items: [TestData(title: "title")])
- .action(TestTableViewCellOptions.CellAction) { data -> Void in
-
+ let row = TableRow(item: TestData(title: "title"))
+ .action(TableRowAction(.custom(TestTableViewCellOptions.CellAction)) { (data) in
+
XCTAssertNotNil(data.cell, "Action data should have a cell")
- XCTAssertNotNil(data.userInfo, "Action data should have a user info dictionary")
- XCTAssertTrue(data.userInfo?[TestTableViewCellOptions.CellActionUserInfoKey] as? String == TestTableViewCellOptions.CellActionUserInfoValue, "UserInfo should have correct value for key")
-
+
expectation.fulfill()
- }
+ })
testController.view.hidden = false
testController.tableDirector += row
@@ -239,5 +190,5 @@ class TabletTests: XCTestCase {
cell?.raiseAction()
waitForExpectationsWithTimeout(1.0, handler: nil)
- }*/
+ }
}
\ No newline at end of file
From f74d35cc8c6b55809d11d6ad6dcb575931213b76 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 06:21:24 +0300
Subject: [PATCH 26/29] update readme
---
README.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 4f053bd..7c0143e 100644
--- a/README.md
+++ b/README.md
@@ -154,7 +154,9 @@ It's never been so easy to deal with table views.
```swift
let users = /* some users array */
-tableDirector += users.filter({ $0.state == .active }).map({ TableRow(item: $0.username) })
+let rows: [Row] = users.filter({ $0.state == .active }).map({ TableRow(item: $0.username) })
+
+tableDirector += rows
```
Done, your table is ready. It's just awesome!
From 89e3113a35a9d9ef4005748bbb731d9e99221521 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 06:23:20 +0300
Subject: [PATCH 27/29] fix travis-ci config
---
.travis.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index f57eb70..9e36ee3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,5 @@ branches:
before_install:
- brew update
- brew reinstall --HEAD xctool
- - cd Tablet
script:
- - xctool clean build test -project TableKit.xcodeproj -scheme TableKit -sdk iphonesimulator
\ No newline at end of file
+ - xctool clean build test -project TableKit.xcodeproj -scheme TableKitTests -sdk iphonesimulator
\ No newline at end of file
From b68bd46ca8152d7938c59e01ee109ac6a8823c4c Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 06:23:57 +0300
Subject: [PATCH 28/29] bump version
---
README.md | 2 +-
TableKit.podspec | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 7c0143e..e0771b7 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
-
+
diff --git a/TableKit.podspec b/TableKit.podspec
index ffb675c..58f4a5c 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 = '0.7.0'
+ s.version = '0.8.0'
s.homepage = 'https://github.com/maxsokolov/TableKit'
s.summary = 'Type-safe declarative table views. Swift 2.2 is required.'
From 1137b47af1bf7f676b371681b9c9770065469868 Mon Sep 17 00:00:00 2001
From: Max Sokolov
Date: Sat, 18 Jun 2016 06:44:34 +0300
Subject: [PATCH 29/29] fix ci
---
.travis.yml | 2 +-
.../xcshareddata/xcschemes/TableKit.xcscheme | 19 +++++++++++++++++++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 9e36ee3..00df090 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,4 +7,4 @@ before_install:
- brew update
- brew reinstall --HEAD xctool
script:
- - xctool clean build test -project TableKit.xcodeproj -scheme TableKitTests -sdk iphonesimulator
\ No newline at end of file
+ - xctool clean build test -project TableKit.xcodeproj -scheme TableKit -sdk iphonesimulator
\ No newline at end of file
diff --git a/TableKit.xcodeproj/xcshareddata/xcschemes/TableKit.xcscheme b/TableKit.xcodeproj/xcshareddata/xcschemes/TableKit.xcscheme
index 9f7535f..6bd5e4d 100644
--- a/TableKit.xcodeproj/xcshareddata/xcschemes/TableKit.xcscheme
+++ b/TableKit.xcodeproj/xcshareddata/xcschemes/TableKit.xcscheme
@@ -28,7 +28,26 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
+
+
+
+
+
+
+
+