Merge pull request #17 from maxsokolov/develop

Support Carthage and Swift Package Manager
This commit is contained in:
Max Sokolov 2016-06-13 14:55:24 +04:00 committed by GitHub
commit 885977b0ef
32 changed files with 595 additions and 376 deletions

View File

@ -21,22 +21,16 @@ class MainController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
/*let rowBuilder = TableRowBuilder<String, StoryboardImageTableViewCell>(items: ["1", "1", "1", "1"])
.action(.click) { [unowned self] data in
self.performSegueWithIdentifier("headerfooter", sender: nil)
}*/
let a = TableRowAction<String, StoryboardImageTableViewCell>(.click) {
(row) in
(data) in
print("3")
print("3", data.item)
}
let b = TableRowBuilder<String, StoryboardImageTableViewCell>(items: ["1", "2", "3"], actions: [a])
let row1 = TableRow<String, StoryboardImageTableViewCell>(item: "1")
let row2 = TableRow<String, StoryboardImageTableViewCell>(item: "2")
@ -45,24 +39,28 @@ class MainController: UIViewController {
row1
.action(TableRowAction(.click) { (row) in
.addAction(TableRowAction(.shouldHighlight) { (data) -> Bool in
print("1")
return false
})
.action(TableRowAction(.click) { (row) -> String in
.addAction(TableRowAction(.click) { (data) in
print("2")
return ""
})
let section = TableSection()
section.append(builder: b)
let section = TableSection(headerTitle: "", footerTitle: "", rows: [row1, row2, row3])
//let section = TableSection(headerTitle: "", footerTitle: "", rows: [row1, row2, row3])
tableDirector += [section]
tableDirector.append(section: section)
//tableDirector.append(section: section)

View File

@ -22,12 +22,15 @@ class StoryboardImageTableViewCell: UITableViewCell, ConfigurableCell {
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"
}
static func estimatedHeight() -> CGFloat {
return 500
}
override func layoutSubviews() {
super.layoutSubviews()
contentView.layoutIfNeeded()
subtitleLabel.preferredMaxLayoutWidth = subtitleLabel.bounds.size.width
//contentView.layoutIfNeeded()
//subtitleLabel.preferredMaxLayoutWidth = subtitleLabel.bounds.size.width
}
}

View File

@ -8,7 +8,8 @@
/* Begin PBXBuildFile section */
DA08A0531CF4E9B500BBF1F8 /* StoryboardImageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA08A0521CF4E9B500BBF1F8 /* StoryboardImageTableViewCell.swift */; };
DA9EA7821D0B6B070021F650 /* TableKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9EA7811D0B6B070021F650 /* TableKit.framework */; };
DA9EA7D91D0EC65B0021F650 /* TableKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9EA7D61D0EC5C60021F650 /* TableKit.framework */; };
DA9EA7DA1D0EC65B0021F650 /* TableKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DA9EA7D61D0EC5C60021F650 /* TableKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
DAC2D5CA1C9D303E009E9C19 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D5C91C9D303E009E9C19 /* AppDelegate.swift */; };
DAC2D5CF1C9D30A7009E9C19 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAC2D5CD1C9D30A7009E9C19 /* Main.storyboard */; };
DAC2D5D01C9D30A7009E9C19 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAC2D5CE1C9D30A7009E9C19 /* LaunchScreen.storyboard */; };
@ -18,9 +19,47 @@
DACB717A1CC2D89D00432BD3 /* HeaderFooterController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DACB71791CC2D89D00432BD3 /* HeaderFooterController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
DA9EA7D51D0EC5C60021F650 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DA9EA7D01D0EC5C50021F650 /* TableKit.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = DA9EA7561D0B679A0021F650;
remoteInfo = TableKit;
};
DA9EA7D71D0EC5C60021F650 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DA9EA7D01D0EC5C50021F650 /* TableKit.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = DA9EA7C41D0EC45F0021F650;
remoteInfo = TableKitTests;
};
DA9EA7DB1D0EC65B0021F650 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DA9EA7D01D0EC5C50021F650 /* TableKit.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = DA9EA7551D0B679A0021F650;
remoteInfo = TableKit;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
DA9EA7DD1D0EC65B0021F650 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
DA9EA7DA1D0EC65B0021F650 /* TableKit.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
DA08A0521CF4E9B500BBF1F8 /* StoryboardImageTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StoryboardImageTableViewCell.swift; sourceTree = "<group>"; };
DA9EA7811D0B6B070021F650 /* TableKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TableKit.framework; path = "../../../../../Library/Developer/Xcode/DerivedData/TableKit-blgxvmkyvpocltgadmpliruugomo/Build/Products/Debug-iphonesimulator/TableKit.framework"; sourceTree = "<group>"; };
DA9EA7D01D0EC5C50021F650 /* TableKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = TableKit.xcodeproj; path = ../TableKit.xcodeproj; sourceTree = "<group>"; };
DAB7EB271BEF787300D2AD5E /* TableKitDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TableKitDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
DAC2D5C91C9D303E009E9C19 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
DAC2D5CD1C9D30A7009E9C19 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
@ -37,7 +76,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DA9EA7821D0B6B070021F650 /* TableKit.framework in Frameworks */,
DA9EA7D91D0EC65B0021F650 /* TableKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -47,14 +86,23 @@
DA539C871CF50B1800368ACB /* Frameworks */ = {
isa = PBXGroup;
children = (
DA9EA7811D0B6B070021F650 /* TableKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
DA9EA7D11D0EC5C50021F650 /* Products */ = {
isa = PBXGroup;
children = (
DA9EA7D61D0EC5C60021F650 /* TableKit.framework */,
DA9EA7D81D0EC5C60021F650 /* TableKitTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
DAB7EB1E1BEF787300D2AD5E = {
isa = PBXGroup;
children = (
DA9EA7D01D0EC5C50021F650 /* TableKit.xcodeproj */,
DAC2D5C61C9D2FE5009E9C19 /* Classes */,
DAC2D5CB1C9D3058009E9C19 /* Resources */,
DA539C871CF50B1800368ACB /* Frameworks */,
@ -151,10 +199,12 @@
DAB7EB231BEF787300D2AD5E /* Sources */,
DAB7EB241BEF787300D2AD5E /* Frameworks */,
DAB7EB251BEF787300D2AD5E /* Resources */,
DA9EA7DD1D0EC65B0021F650 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
DA9EA7DC1D0EC65B0021F650 /* PBXTargetDependency */,
);
name = TableKitDemo;
productName = TabletDemo;
@ -188,6 +238,12 @@
mainGroup = DAB7EB1E1BEF787300D2AD5E;
productRefGroup = DAB7EB281BEF787300D2AD5E /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = DA9EA7D11D0EC5C50021F650 /* Products */;
ProjectRef = DA9EA7D01D0EC5C50021F650 /* TableKit.xcodeproj */;
},
);
projectRoot = "";
targets = (
DAB7EB261BEF787300D2AD5E /* TableKitDemo */,
@ -195,6 +251,23 @@
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
DA9EA7D61D0EC5C60021F650 /* TableKit.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = TableKit.framework;
remoteRef = DA9EA7D51D0EC5C60021F650 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
DA9EA7D81D0EC5C60021F650 /* TableKitTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = TableKitTests.xctest;
remoteRef = DA9EA7D71D0EC5C60021F650 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
DAB7EB251BEF787300D2AD5E /* Resources */ = {
isa = PBXResourcesBuildPhase;
@ -223,6 +296,14 @@
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
DA9EA7DC1D0EC65B0021F650 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = TableKit;
targetProxy = DA9EA7DB1D0EC65B0021F650 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
DAB7EB371BEF787300D2AD5E /* Debug */ = {
isa = XCBuildConfiguration;
@ -311,6 +392,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@ -326,6 +408,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";

5
Package.swift Normal file
View File

@ -0,0 +1,5 @@
import PackageDescription
let package = Package(
name: "TableKit"
)

103
README.md
View File

@ -4,11 +4,12 @@
<a href="https://travis-ci.org/maxsokolov/TableKit"><img src="https://api.travis-ci.org/maxsokolov/TableKit.svg" alt="Build Status" /></a>
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/Swift_2.2-compatible-4BC51D.svg?style=flat" alt="Swift 2.2 compatible" /></a>
<img src="https://img.shields.io/badge/platform-iOS-blue.svg?style=flat" alt="Platform iOS" />
<a href="https://cocoapods.org/pods/tablekit"><img src="https://img.shields.io/badge/pod-0.5.0-blue.svg" alt="CocoaPods compatible" /></a>
<a href="https://cocoapods.org/pods/tablekit"><img src="https://img.shields.io/badge/pod-0.7.0-blue.svg" alt="CocoaPods compatible" /></a>
<a href="https://raw.githubusercontent.com/maxsokolov/tablekit/master/LICENSE"><img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="License: MIT" /></a>
</p>
TableKit is a super lightweight yet powerful generic library that handles a complexity of UITableView's datasource and delegate methods in a Swift environment. Tablet's goal is to provide an easiest way to create complex table views. With Tablet you don't have to write a messy code of `switch` or `if` statements when you deal with bunch of different cells in different sections.
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
@ -22,8 +23,102 @@ TableKit is a super lightweight yet powerful generic library that handles a comp
- [x] Extensibility
- [x] Tests
Docs will be updated soon.
## Usage
Create your rows:
```swift
let row1 = TableRow<String, StringTableViewCell>(item: "1")
let row2 = TableRow<String, IntTableViewCell>(item: 2)
let row3 = TableRow<String, FloatTableViewCell>(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 += 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) {
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<String, StringTableViewCell>(.click) { (data) in
}
let row = TableRow<String, StringTableViewCell>(item: "some", actions: [action])
```
Or, using nice chaining approach:
```swift
let row = TableRow<String, StringTableViewCell>(item: "some")
row
.addAction(TableRowAction(.click) { (data) in
})
.addAction(TableRowAction(.shouldHighlight) { (data) -> Bool in
return false
})
```
## 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<String, StringTableViewCell> {
// 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<String, StringTableViewCell>(items: ["1", "2", "3"], actions: [actions])
section.append(builder: builder)
```
## Installation
#### CocoaPods
To integrate TableKit into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
pod 'TableKit'
```
#### Carthage
Add the line `github "maxsokolov/tablekit"` to your `Cartfile`
## Requirements
- iOS 8.0+
- Xcode 7.0+
## License
Tablet is available under the MIT license. See LICENSE for details.
TableKit is available under the MIT license. See LICENSE for details.

View File

@ -21,9 +21,9 @@
import UIKit
public protocol ConfigurableCell {
associatedtype T
static func reusableIdentifier() -> String
static func estimatedHeight() -> CGFloat
static func defaultHeight() -> CGFloat?
@ -31,15 +31,15 @@ public protocol ConfigurableCell {
}
public extension ConfigurableCell where Self: UITableViewCell {
static func reusableIdentifier() -> String {
return String(self)
}
static func estimatedHeight() -> CGFloat {
return UITableViewAutomaticDimension
}
static func defaultHeight() -> CGFloat? {
return nil
}

View File

@ -18,37 +18,20 @@
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// -
/*public func +=(left: TableDirector, right: RowBuilder) {
left.append(section: TableSectionBuilder(rows: [right]))
}
public func +=(left: TableDirector, right: [RowBuilder]) {
left.append(section: TableSectionBuilder(rows: right))
}
public func +=(left: TableDirector, right: TableSectionBuilder) {
// --
public func +=(left: TableDirector, right: TableSection) {
left.append(section: right)
}
public func +=(left: TableDirector, right: [TableSectionBuilder]) {
public func +=(left: TableDirector, right: [TableSection]) {
left.append(sections: right)
}
// -
public func +=<DataType, CellType>(left: TableRowBuilder<DataType, CellType>, right: DataType) {
left.append(items: [right])
}
public func +=<DataType, CellType>(left: TableRowBuilder<DataType, CellType>, right: [DataType]) {
left.append(items: right)
}
// -
public func +=(left: TableSectionBuilder, right: RowBuilder) {
// --
public func +=(left: TableSection, right: Row) {
left.append(row: right)
}
public func +=(left: TableSectionBuilder, right: [RowBuilder]) {
public func +=(left: TableSection, right: [Row]) {
left.append(rows: right)
}*/
}

View File

@ -20,35 +20,15 @@
import UIKit
struct TabletNotifications {
static let CellAction = "TabletNotificationsCellAction"
struct TableKitNotifications {
static let CellAction = "TableKitNotificationsCellAction"
}
public class ActionData<DataType, CellType> {
public let cell: CellType?
public let item: DataType
public let itemIndex: Int
public let indexPath: NSIndexPath
public let userInfo: [NSObject: AnyObject]?
init(cell: CellType?, indexPath: NSIndexPath, item: DataType, itemIndex: Int, userInfo: [NSObject: AnyObject]?) {
self.cell = cell
self.indexPath = indexPath
self.item = item
self.itemIndex = itemIndex
self.userInfo = userInfo
}
}
/**
A custom action that you can trigger from your cell.
You can eacily catch actions using a chaining manner with your row builder.
*/
public class Action {
public class TableCellAction {
/// The cell that triggers an action.
public let cell: UITableViewCell
@ -67,6 +47,6 @@ public class Action {
}
public func invoke() {
NSNotificationCenter.defaultCenter().postNotificationName(TabletNotifications.CellAction, object: self, userInfo: userInfo)
NSNotificationCenter.defaultCenter().postNotificationName(TableKitNotifications.CellAction, object: self, userInfo: userInfo)
}
}

View File

@ -26,8 +26,8 @@ import UIKit
public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
public private(set) weak var tableView: UITableView?
private weak var scrollDelegate: UIScrollViewDelegate?
public private(set) var sections = [TableSection]()
private weak var scrollDelegate: UIScrollViewDelegate?
public init(tableView: UITableView, scrollDelegate: UIScrollViewDelegate? = nil) {
super.init()
@ -37,7 +37,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
self.tableView?.delegate = self
self.tableView?.dataSource = self
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(didReceiveAction), name: TabletNotifications.CellAction, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(didReceiveAction), name: TableKitNotifications.CellAction, object: nil)
}
deinit {
@ -64,13 +64,14 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
// MARK: - Internal -
func hasAction(action: TableRowActionType, atIndexPath indexPath: NSIndexPath) -> Bool {
return sections[indexPath.section].items[indexPath.row].hasAction(action)
}
func didReceiveAction(notification: NSNotification) {
if let action = notification.object as? Action, indexPath = tableView?.indexPathForCell(action.cell) {
//let builder = builderAtIndexPath(indexPath)
//builder.0.invoke(action: .custom(action.key), cell: action.cell, indexPath: indexPath, itemIndex: builder.1, userInfo: notification.userInfo)
}
guard let action = notification.object as? TableCellAction, indexPath = tableView?.indexPathForCell(action.cell) else { return }
invoke(action: .custom(action.key), cell: action.cell, indexPath: indexPath)
}
// MARK: - Height
@ -160,25 +161,33 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return invoke(action: .shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true
}
/*func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
return invokeAction(.willSelect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? NSIndexPath
}*/
public func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
if hasAction(.willSelect, atIndexPath: indexPath) {
return invoke(action: .willSelect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? NSIndexPath
}
return indexPath
}
// MARK: - Sections manipulation -
public func append(section section: TableSection) {
public func append(section section: TableSection) -> Self {
append(sections: [section])
return self
}
public func append(sections sections: [TableSection]) {
public func append(sections sections: [TableSection]) -> Self {
sections.forEach { $0.tableDirector = self }
self.sections.appendContentsOf(sections)
return self
}
public func clear() {
public func clear() -> Self {
sections.removeAll()
return self
}
}

View File

@ -41,7 +41,7 @@ public protocol Row: RowConfigurable, RowActionable {
public class TableRow<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell>: Row {
public let item: ItemType
private var actions = [String: RowAction]()
private lazy var actions = [String: TableRowAction<ItemType, CellType>]()
public var reusableIdentifier: String {
return CellType.reusableIdentifier()
@ -56,7 +56,9 @@ public class TableRow<ItemType, CellType: ConfigurableCell where CellType.T == I
}
public init(item: ItemType, actions: [TableRowAction<ItemType, CellType>]? = nil) {
self.item = item
actions?.forEach { self.actions[$0.type.key] = $0 }
}
// MARK: - RowConfigurable -
@ -68,7 +70,7 @@ public class TableRow<ItemType, CellType: ConfigurableCell where CellType.T == I
// MARK: - RowActionable -
public func invoke(action: TableRowActionType, cell: UITableViewCell?, path: NSIndexPath) -> Any? {
return actions[action.key]?.invoke()
return actions[action.key]?.invoke(item: item, cell: cell, path: path)
}
public func hasAction(action: TableRowActionType) -> Bool {
@ -77,7 +79,7 @@ public class TableRow<ItemType, CellType: ConfigurableCell where CellType.T == I
// MARK: - actions -
public func action(action: TableRowAction<ItemType, CellType>) -> Self {
public func addAction(action: TableRowAction<ItemType, CellType>) -> Self {
actions[action.type.key] = action
return self

View File

@ -31,7 +31,7 @@ public enum TableRowActionType {
case shouldHighlight
case height
case custom(String)
var key: String {
switch (self) {
@ -43,26 +43,40 @@ public enum TableRowActionType {
}
}
protocol RowAction {
public class TableRowActionData<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell> {
func invoke() -> Any?
public let item: ItemType
public let cell: CellType?
public let path: NSIndexPath
public let userInfo: [NSObject: AnyObject]?
init(item: ItemType, cell: CellType?, path: NSIndexPath, userInfo: [NSObject: AnyObject]?) {
self.item = item
self.cell = cell
self.path = path
self.userInfo = userInfo
}
}
public class TableRowAction<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell>: RowAction {
public class TableRowAction<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell> {
public let type: TableRowActionType
private let handler: ((data: TableRowActionData<ItemType, CellType>) -> Any?)
public init(_ type: TableRowActionType, handler: (data: TableRowActionData<ItemType, CellType>) -> Void) {
public init(_ type: TableRowActionType, handler: (row: TableRow<ItemType, CellType>) -> Void) {
self.type = type
self.handler = handler
}
public init<T>(_ type: TableRowActionType, handler: (row: TableRow<ItemType, CellType>) -> T) {
public init<T>(_ type: TableRowActionType, handler: (data: TableRowActionData<ItemType, CellType>) -> T) {
self.type = type
self.handler = handler
}
// MARK: - RowAction -
func invoke() -> Any? {
return nil
func invoke(item item: ItemType, cell: UITableViewCell?, path: NSIndexPath) -> Any? {
return handler(data: TableRowActionData(item: item, cell: cell as? CellType, path: path, userInfo: nil))
}
}

View File

@ -0,0 +1,58 @@
//
// Copyright (c) 2015 Max Sokolov https://twitter.com/max_sokolov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import UIKit
public protocol RowBuilder {
func rowItems() -> [Row]?
}
public class TableRowBuilder<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell>: RowBuilder {
public var items: [ItemType]?
public var actions: [TableRowAction<ItemType, CellType>]?
public init(handler: (TableRowBuilder) -> ()) {
handler(self)
}
public init(items: [ItemType], actions: [TableRowAction<ItemType, CellType>]? = nil) {
self.items = items
self.actions = actions
}
// MARK: - RowBuilder -
public func rowItems() -> [Row]? {
return items?.map { TableRow<ItemType, CellType>(item: $0, actions: actions) }
}
}
public extension TableSection {
public func append(builder builder: RowBuilder) {
if let rows = builder.rowItems() {
append(rows: rows)
}
}
}

View File

@ -20,10 +20,6 @@
import UIKit
/**
Responsible for building a certain table view section.
Can host several row builders.
*/
public class TableSection {
weak var tableDirector: TableDirector?
@ -36,7 +32,6 @@ public class TableSection {
public private(set) var headerView: UIView?
public private(set) var footerView: UIView?
/// A total number of rows in section of each row builder.
public var numberOfRows: Int {
return items.count
}
@ -48,14 +43,14 @@ public class TableSection {
}
}
public convenience init(headerTitle: String?, footerTitle: String?, rows: [Row]?) {
public convenience init(headerTitle: String?, footerTitle: String?, rows: [Row]? = nil) {
self.init(rows: rows)
self.headerTitle = headerTitle
self.footerTitle = footerTitle
}
public convenience init(headerView: UIView?, footerView: UIView?, rows: [Row]?) {
public convenience init(headerView: UIView?, footerView: UIView?, rows: [Row]? = nil) {
self.init(rows: rows)
self.headerView = headerView
@ -71,10 +66,8 @@ public class TableSection {
public func append(row row: Row) {
append(rows: [row])
}
public func append(rows rows: [Row]) {
//if let director = tableDirector { rows.forEach { $0.willUpdateDirector(director) } }
//builders.appendContentsOf(rows)
items.appendContentsOf(rows)
}
}

View File

@ -2,7 +2,7 @@ Pod::Spec.new do |s|
s.name = 'TableKit'
s.module_name = 'TableKit'
s.version = '0.6.0'
s.version = '0.7.0'
s.homepage = 'https://github.com/maxsokolov/TableKit'
s.summary = 'Type-safe declarative table views. Swift 2.2 is required.'
@ -12,6 +12,6 @@ Pod::Spec.new do |s|
s.platforms = { :ios => '8.0' }
s.ios.deployment_target = '8.0'
s.source_files = 'TableKit/*.swift'
s.source_files = 'Sources/*.swift'
s.source = { :git => 'https://github.com/maxsokolov/TableKit.git', :tag => s.version }
end

View File

@ -7,31 +7,44 @@
objects = {
/* Begin PBXBuildFile section */
DA9EA7711D0B68460021F650 /* ConfigurableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7681D0B68460021F650 /* ConfigurableCell.swift */; };
DA9EA7721D0B68460021F650 /* HeightStrategy.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7691D0B68460021F650 /* HeightStrategy.swift */; };
DA9EA7731D0B68460021F650 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA76A1D0B68460021F650 /* Operators.swift */; };
DA9EA7741D0B68460021F650 /* TableDirector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA76B1D0B68460021F650 /* TableDirector.swift */; };
DA9EA7751D0B68460021F650 /* TableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA76C1D0B68460021F650 /* TableRow.swift */; };
DA9EA7761D0B68460021F650 /* TableRowAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA76D1D0B68460021F650 /* TableRowAction.swift */; };
DA9EA7771D0B68460021F650 /* TableRowBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA76E1D0B68460021F650 /* TableRowBuilder.swift */; };
DA9EA7781D0B68460021F650 /* TableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA76F1D0B68460021F650 /* TableSection.swift */; };
DA9EA7791D0B68460021F650 /* Tablet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7701D0B68460021F650 /* Tablet.swift */; };
DA9EA7801D0B689C0021F650 /* TableKit.h in Headers */ = {isa = PBXBuildFile; fileRef = DA9EA77E1D0B689C0021F650 /* TableKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
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 */; };
DA9EA7B21D0EC2C90021F650 /* TableCellAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7A91D0EC2C90021F650 /* TableCellAction.swift */; };
DA9EA7B31D0EC2C90021F650 /* TableDirector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7AA1D0EC2C90021F650 /* TableDirector.swift */; };
DA9EA7B41D0EC2C90021F650 /* TableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7AB1D0EC2C90021F650 /* TableRow.swift */; };
DA9EA7B51D0EC2C90021F650 /* TableRowAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7AC1D0EC2C90021F650 /* TableRowAction.swift */; };
DA9EA7B61D0EC2C90021F650 /* TableRowBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7AD1D0EC2C90021F650 /* TableRowBuilder.swift */; };
DA9EA7B71D0EC2C90021F650 /* TableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7AE1D0EC2C90021F650 /* TableSection.swift */; };
DA9EA7C91D0EC45F0021F650 /* TableKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9EA7561D0B679A0021F650 /* TableKit.framework */; };
DA9EA7CF1D0EC4930021F650 /* TableKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA9EA7BE1D0EC41D0021F650 /* TableKitTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
DA9EA7CA1D0EC45F0021F650 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DA9EA74D1D0B679A0021F650 /* Project object */;
proxyType = 1;
remoteGlobalIDString = DA9EA7551D0B679A0021F650;
remoteInfo = TableKit;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
DA9EA7561D0B679A0021F650 /* TableKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TableKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DA9EA7681D0B68460021F650 /* ConfigurableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurableCell.swift; sourceTree = "<group>"; };
DA9EA7691D0B68460021F650 /* HeightStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeightStrategy.swift; sourceTree = "<group>"; };
DA9EA76A1D0B68460021F650 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
DA9EA76B1D0B68460021F650 /* TableDirector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableDirector.swift; sourceTree = "<group>"; };
DA9EA76C1D0B68460021F650 /* TableRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRow.swift; sourceTree = "<group>"; };
DA9EA76D1D0B68460021F650 /* TableRowAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRowAction.swift; sourceTree = "<group>"; };
DA9EA76E1D0B68460021F650 /* TableRowBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRowBuilder.swift; sourceTree = "<group>"; };
DA9EA76F1D0B68460021F650 /* TableSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableSection.swift; sourceTree = "<group>"; };
DA9EA7701D0B68460021F650 /* Tablet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tablet.swift; sourceTree = "<group>"; };
DA9EA77D1D0B689C0021F650 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DA9EA77E1D0B689C0021F650 /* TableKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableKit.h; sourceTree = "<group>"; };
DA9EA7A61D0EC2C90021F650 /* ConfigurableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurableCell.swift; sourceTree = "<group>"; };
DA9EA7A71D0EC2C90021F650 /* HeightStrategy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeightStrategy.swift; sourceTree = "<group>"; };
DA9EA7A81D0EC2C90021F650 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = "<group>"; };
DA9EA7A91D0EC2C90021F650 /* TableCellAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableCellAction.swift; sourceTree = "<group>"; };
DA9EA7AA1D0EC2C90021F650 /* TableDirector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableDirector.swift; sourceTree = "<group>"; };
DA9EA7AB1D0EC2C90021F650 /* TableRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRow.swift; sourceTree = "<group>"; };
DA9EA7AC1D0EC2C90021F650 /* TableRowAction.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRowAction.swift; sourceTree = "<group>"; };
DA9EA7AD1D0EC2C90021F650 /* TableRowBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRowBuilder.swift; sourceTree = "<group>"; };
DA9EA7AE1D0EC2C90021F650 /* TableSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableSection.swift; sourceTree = "<group>"; };
DA9EA7B91D0EC34E0021F650 /* TableKit.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TableKit.plist; sourceTree = "<group>"; };
DA9EA7BA1D0EC34E0021F650 /* TableKitTests.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = TableKitTests.plist; sourceTree = "<group>"; };
DA9EA7BE1D0EC41D0021F650 /* TableKitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableKitTests.swift; sourceTree = "<group>"; };
DA9EA7C41D0EC45F0021F650 /* TableKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TableKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -42,15 +55,24 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
DA9EA7C11D0EC45F0021F650 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
DA9EA7C91D0EC45F0021F650 /* TableKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
DA9EA74C1D0B679A0021F650 = {
isa = PBXGroup;
children = (
DA9EA7671D0B68340021F650 /* Classes */,
DA9EA7B81D0EC31B0021F650 /* Configs */,
DA9EA7571D0B679A0021F650 /* Products */,
DA9EA77C1D0B68860021F650 /* Supporting Files */,
DA9EA7A51D0EC2B90021F650 /* Sources */,
DA9EA7BD1D0EC3D70021F650 /* Tests */,
);
sourceTree = "<group>";
};
@ -58,33 +80,42 @@
isa = PBXGroup;
children = (
DA9EA7561D0B679A0021F650 /* TableKit.framework */,
DA9EA7C41D0EC45F0021F650 /* TableKitTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
DA9EA7671D0B68340021F650 /* Classes */ = {
DA9EA7A51D0EC2B90021F650 /* Sources */ = {
isa = PBXGroup;
children = (
DA9EA7681D0B68460021F650 /* ConfigurableCell.swift */,
DA9EA7691D0B68460021F650 /* HeightStrategy.swift */,
DA9EA76A1D0B68460021F650 /* Operators.swift */,
DA9EA76B1D0B68460021F650 /* TableDirector.swift */,
DA9EA76C1D0B68460021F650 /* TableRow.swift */,
DA9EA76D1D0B68460021F650 /* TableRowAction.swift */,
DA9EA76E1D0B68460021F650 /* TableRowBuilder.swift */,
DA9EA76F1D0B68460021F650 /* TableSection.swift */,
DA9EA7701D0B68460021F650 /* Tablet.swift */,
DA9EA7AA1D0EC2C90021F650 /* TableDirector.swift */,
DA9EA7AB1D0EC2C90021F650 /* TableRow.swift */,
DA9EA7AD1D0EC2C90021F650 /* TableRowBuilder.swift */,
DA9EA7AC1D0EC2C90021F650 /* TableRowAction.swift */,
DA9EA7AE1D0EC2C90021F650 /* TableSection.swift */,
DA9EA7A91D0EC2C90021F650 /* TableCellAction.swift */,
DA9EA7A61D0EC2C90021F650 /* ConfigurableCell.swift */,
DA9EA7A81D0EC2C90021F650 /* Operators.swift */,
DA9EA7A71D0EC2C90021F650 /* HeightStrategy.swift */,
);
name = Classes;
path = Sources;
sourceTree = "<group>";
};
DA9EA77C1D0B68860021F650 /* Supporting Files */ = {
DA9EA7B81D0EC31B0021F650 /* Configs */ = {
isa = PBXGroup;
children = (
DA9EA77D1D0B689C0021F650 /* Info.plist */,
DA9EA77E1D0B689C0021F650 /* TableKit.h */,
DA9EA7B91D0EC34E0021F650 /* TableKit.plist */,
DA9EA7BA1D0EC34E0021F650 /* TableKitTests.plist */,
);
name = "Supporting Files";
path = Configs;
sourceTree = "<group>";
};
DA9EA7BD1D0EC3D70021F650 /* Tests */ = {
isa = PBXGroup;
children = (
DA9EA7BE1D0EC41D0021F650 /* TableKitTests.swift */,
);
path = Tests;
sourceTree = "<group>";
};
/* End PBXGroup section */
@ -94,7 +125,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
DA9EA7801D0B689C0021F650 /* TableKit.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -119,18 +149,40 @@
productReference = DA9EA7561D0B679A0021F650 /* TableKit.framework */;
productType = "com.apple.product-type.framework";
};
DA9EA7C31D0EC45F0021F650 /* TableKitTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = DA9EA7CC1D0EC45F0021F650 /* Build configuration list for PBXNativeTarget "TableKitTests" */;
buildPhases = (
DA9EA7C01D0EC45F0021F650 /* Sources */,
DA9EA7C11D0EC45F0021F650 /* Frameworks */,
DA9EA7C21D0EC45F0021F650 /* Resources */,
);
buildRules = (
);
dependencies = (
DA9EA7CB1D0EC45F0021F650 /* PBXTargetDependency */,
);
name = TableKitTests;
productName = TableKitTests;
productReference = DA9EA7C41D0EC45F0021F650 /* TableKitTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
DA9EA74D1D0B679A0021F650 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0730;
ORGANIZATIONNAME = "Max Sokolov";
TargetAttributes = {
DA9EA7551D0B679A0021F650 = {
CreatedOnToolsVersion = 7.3;
};
DA9EA7C31D0EC45F0021F650 = {
CreatedOnToolsVersion = 7.3;
};
};
};
buildConfigurationList = DA9EA7501D0B679A0021F650 /* Build configuration list for PBXProject "TableKit" */;
@ -146,6 +198,7 @@
projectRoot = "";
targets = (
DA9EA7551D0B679A0021F650 /* TableKit */,
DA9EA7C31D0EC45F0021F650 /* TableKitTests */,
);
};
/* End PBXProject section */
@ -158,6 +211,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
DA9EA7C21D0EC45F0021F650 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -165,20 +225,36 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DA9EA7711D0B68460021F650 /* ConfigurableCell.swift in Sources */,
DA9EA7721D0B68460021F650 /* HeightStrategy.swift in Sources */,
DA9EA7781D0B68460021F650 /* TableSection.swift in Sources */,
DA9EA7751D0B68460021F650 /* TableRow.swift in Sources */,
DA9EA7761D0B68460021F650 /* TableRowAction.swift in Sources */,
DA9EA7741D0B68460021F650 /* TableDirector.swift in Sources */,
DA9EA7771D0B68460021F650 /* TableRowBuilder.swift in Sources */,
DA9EA7791D0B68460021F650 /* Tablet.swift in Sources */,
DA9EA7731D0B68460021F650 /* Operators.swift in Sources */,
DA9EA7AF1D0EC2C90021F650 /* ConfigurableCell.swift in Sources */,
DA9EA7B31D0EC2C90021F650 /* TableDirector.swift in Sources */,
DA9EA7B71D0EC2C90021F650 /* TableSection.swift in Sources */,
DA9EA7B01D0EC2C90021F650 /* HeightStrategy.swift in Sources */,
DA9EA7B51D0EC2C90021F650 /* TableRowAction.swift in Sources */,
DA9EA7B21D0EC2C90021F650 /* TableCellAction.swift in Sources */,
DA9EA7B11D0EC2C90021F650 /* Operators.swift in Sources */,
DA9EA7B41D0EC2C90021F650 /* TableRow.swift in Sources */,
DA9EA7B61D0EC2C90021F650 /* TableRowBuilder.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
DA9EA7C01D0EC45F0021F650 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
DA9EA7CF1D0EC4930021F650 /* TableKitTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
DA9EA7CB1D0EC45F0021F650 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DA9EA7551D0B679A0021F650 /* TableKit */;
targetProxy = DA9EA7CA1D0EC45F0021F650 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
DA9EA75C1D0B679A0021F650 /* Debug */ = {
isa = XCBuildConfiguration;
@ -218,7 +294,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -261,7 +337,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
@ -279,7 +355,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
INFOPLIST_FILE = "$(SRCROOT)/Configs/TableKit.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@ -298,7 +374,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = "$(SRCROOT)/Info.plist";
INFOPLIST_FILE = "$(SRCROOT)/Configs/TableKit.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
@ -308,6 +384,28 @@
};
name = Release;
};
DA9EA7CD1D0EC45F0021F650 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = Configs/TableKitTests.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
DA9EA7CE1D0EC45F0021F650 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = Configs/TableKitTests.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -329,6 +427,14 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
DA9EA7CC1D0EC45F0021F650 /* Build configuration list for PBXNativeTarget "TableKitTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
DA9EA7CD1D0EC45F0021F650 /* Debug */,
DA9EA7CE1D0EC45F0021F650 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = DA9EA74D1D0B679A0021F650 /* Project object */;

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0730"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DA9EA7551D0B679A0021F650"
BuildableName = "TableKit.framework"
BlueprintName = "TableKit"
ReferencedContainer = "container:TableKit.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DA9EA7551D0B679A0021F650"
BuildableName = "TableKit.framework"
BlueprintName = "TableKit"
ReferencedContainer = "container:TableKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "DA9EA7551D0B679A0021F650"
BuildableName = "TableKit.framework"
BlueprintName = "TableKit"
ReferencedContainer = "container:TableKit.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:TableKit/TableKit.xcodeproj">
</FileRef>
<FileRef
location = "group:TableKitDemo/TableKitDemo.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,19 +0,0 @@
//
// TableKit.h
// TableKit
//
// Created by Max Sokolov on 11/06/16.
// Copyright © 2016 Max Sokolov. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for TableKit.
FOUNDATION_EXPORT double TableKitVersionNumber;
//! Project version string for TableKit.
FOUNDATION_EXPORT const unsigned char TableKitVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <TableKit/PublicHeader.h>

View File

@ -1,168 +0,0 @@
//
// Copyright (c) 2015 Max Sokolov https://twitter.com/max_sokolov
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import UIKit
public typealias ReturnValue = AnyObject?
/**
Responsible for building cells of given type and passing items to them.
*/
/*public class TableRowBuilder<DataType, CellType: ConfigurableCell where CellType.T == DataType, CellType: UITableViewCell> : RowBuilder {
public private(set) weak var tableDirector: TableDirector?
private var heightStrategy: HeightStrategy?
private var actions = [String: ActionHandler<DataType, CellType>]()
private var items = [DataType]()
public func reusableIdentifier(_: Int) -> String {
return CellType.reusableIdentifier()
}
public var numberOfRows: Int {
return items.count
}
// MARK: - Initializers -
public init(item: DataType) {
items.append(item)
}
public init(items: [DataType]? = nil) {
if let items = items {
self.items.appendContentsOf(items)
}
}
// MARK: - RowHeightCalculatable -
public func rowHeight(index: Int, indexPath: NSIndexPath) -> CGFloat {
return CellType.defaultHeight() ?? heightStrategy?.height(item(index: index), indexPath: indexPath, cell: CellType.self) ?? UITableViewAutomaticDimension
}
public func estimatedRowHeight(index: Int, indexPath: NSIndexPath) -> CGFloat {
return CellType.estimatedHeight()
}
// MARK: - RowConfigurable -
public func configure(cell: UITableViewCell, path: NSIndexPath, index: Int) {
(cell as? CellType)?.configure(items[index])
}
// MARK: - Chaining actions -
public func addAction(action: TableRowAction<DataType, CellType>) {
}
public func action(key: String, handler: (data: ActionData<DataType, CellType>) -> Void) -> Self {
actions[key] = .Handler(handler)
return self
}
public func action(type: ActionType, handler: (data: ActionData<DataType, CellType>) -> Void) -> Self {
actions[type.key] = .Handler(handler)
return self
}
public func valueAction(type: ActionType, handler: (data: ActionData<DataType, CellType>) -> ReturnValue) -> Self {
actions[type.key] = .ValueHandler(handler)
return self
}
public func invoke(action action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int, userInfo: [NSObject: AnyObject]?) -> AnyObject? {
if case .configure = action {
(cell as? CellType)?.configure(item(index: itemIndex))
}
if let action = actions[action.key] {
return action.invoke(ActionData(cell: cell as? CellType, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex, userInfo: userInfo))
}
return nil
}
private func registerCell(inTableView tableView: UITableView) {
if tableView.dequeueReusableCellWithIdentifier(reusableIdentifier(0)) != nil {
return
}
let resource = String(CellType)
let bundle = NSBundle(forClass: CellType.self)
if let _ = bundle.pathForResource(resource, ofType: "nib") { // existing cell
tableView.registerNib(UINib(nibName: resource, bundle: bundle), forCellReuseIdentifier: reusableIdentifier(0))
} else {
tableView.registerClass(CellType.self, forCellReuseIdentifier: reusableIdentifier(0))
}
}
public func willUpdateDirector(director: TableDirector?) {
tableDirector = director
heightStrategy = PrototypeHeightStrategy()
heightStrategy?.tableView = director?.tableView
}
// MARK: - Items manipulation -
public func delete(indexes indexes: [Int], animated: UITableViewRowAnimation) -> Self {
return self
}
public func insert(items: [DataType], atIndex index: Int, animated: UITableViewRowAnimation) -> Self {
self.items.insertContentsOf(items, at: index)
return self
}
public func move(indexes: [Int], toIndexes: [Int]) -> Self {
return self
}
public func update(index index: Int, item: DataType, animated: UITableViewRowAnimation) -> Self {
return self
}
public func item(index index: Int) -> DataType {
return items[index]
}
public func append(items items: [DataType]) {
self.items.appendContentsOf(items)
}
public func clear() {
items.removeAll()
}
}*/

View File

@ -19,7 +19,7 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import XCTest
import Tablet
import TableKit
class TestController: UITableViewController {
@ -45,7 +45,7 @@ struct TestTableViewCellOptions {
static let EstimatedHeight: Float = 255
}
class TestTableViewCell: UITableViewCell, ConfigurableCell {
/*class TestTableViewCell: UITableViewCell, ConfigurableCell {
typealias T = TestData
@ -197,4 +197,4 @@ class TabletTests: XCTestCase {
waitForExpectationsWithTimeout(1.0, handler: nil)
}
}
}*/