#TableKit
TableKit is a super lightweight yet powerful generic library that allows you to build complex table views in a declarative type-safe manner.
It hides a complexity of `UITableViewDataSource` and `UITableViewDelegate` methods behind the scene, so your code will be look clean, easy to read and nice to maintain.
## 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.)
- [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
## Getting Started
An [example app](Demo) is included demonstrating TableKit's functionality.
#### Basic usage
Create your rows:
```swift
let row1 = TableRow(item: "1")
let row2 = TableRow(item: 2)
let row3 = TableRow(item: 3.0)
```
Put rows into section:
```swift
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:
```swift
class StringTableViewCell: UITableViewCell, ConfigurableCell {
typealias T = String
func configure(string: T, isPrototype: Bool) {
titleLabel.text = string
}
static func estimatedHeight() -> CGFloat {
return 44
}
}
```
You could have as many rows and sections as you need.
#### Row actions
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])
```
Or, using nice chaining approach:
```swift
let row = TableRow(item: "some")
.action(TableRowAction(.click) { (data) in
})
.action(TableRowAction(.shouldHighlight) { (data) -> Bool in
return false
})
```
You could find all available actions [here](Sources/TableRowAction.swift).
#### 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 {
// do some additional setup here
$0.items = ["1", "2", "3"]
$0.actions = [action]
}
section.append(builder: builder)
```
Or if you don't need an additional setup for your data, just use standart init:
```swift
let builder = TableRowBuilder(items: ["1", "2", "3"], actions: [actions])
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
class StringTableViewCell: UITableViewCell, ConfigurableCell {
// ...
static func estimatedHeight() -> CGFloat {
return 44
}
}
```
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 for you [behind the scene](Sources/HeightStrategy.swift), 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)
}
}
override func layoutSubviews() {
super.layoutSubviews()
contentView.layoutIfNeeded()
multilineLabel.preferredMaxLayoutWidth = multilineLabel.bounds.size.width
}
}
```
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 */
let rows: [Row] = users.filter({ $0.state == .active }).map({ TableRow(item: $0.username) })
tableDirector += rows
```
Done, your table is ready. It's just awesome!
## Installation
#### CocoaPods
To integrate TableKit into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
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
- iOS 7.0+
- Xcode 7.0+
## License
TableKit is available under the MIT license. See LICENSE for details.