commit
a28422c1af
|
|
@ -0,0 +1,11 @@
|
|||
language: objective-c
|
||||
osx_image: xcode7.2
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
before_install:
|
||||
- cd Tablet
|
||||
script:
|
||||
- xctool clean build test -project Tablet.xcodeproj -scheme Tablet -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6' GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES
|
||||
after_success:
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
37
README.md
37
README.md
|
|
@ -1,19 +1,32 @@
|
|||

|
||||
#Tablet
|
||||
|
||||
<p align="left">
|
||||
<a href="https://travis-ci.org/maxsokolov/tablet"><img src="https://travis-ci.org/maxsokolov/tablet.svg" alt="Build Status" /></a>
|
||||
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/Swift2-compatible-4BC51D.svg?style=flat" alt="Swift 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/tablet"><img src="https://img.shields.io/badge/pod-0.2.4-blue.svg" alt="CocoaPods compatible" /></a>
|
||||
<a href="https://cocoapods.org/pods/tablet"><img src="https://img.shields.io/badge/pod-0.3.0-blue.svg" alt="CocoaPods compatible" /></a>
|
||||
<a href="https://raw.githubusercontent.com/maxsokolov/tablet/master/LICENSE"><img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="License: MIT" /></a>
|
||||
</p>
|
||||
|
||||
Tablet 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.
|
||||
|
||||
That's almost all you need in your controller to build a bunch of cells in a section:
|
||||
## Features
|
||||
|
||||
- [x] Type-safe cells based on generics
|
||||
- [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
|
||||
- [x] Support cells created from code, xib, or storyboard
|
||||
- [x] Automatic xib/classes registration
|
||||
- [x] No need to subclass
|
||||
- [x] Extensibility
|
||||
- [x] Tests
|
||||
|
||||
That's almost all you need in your controller to build a bunch of cells in a section 😘:
|
||||
```swift
|
||||
TableConfigurableRowBuilder<String, MyTableViewCell>(items: ["1", "2", "3", "4", "5"], estimatedRowHeight: 42)
|
||||
TableConfigurableRowBuilder<String, MyTableViewCell>(items: ["1", "2", "3", "4", "5"])
|
||||
```
|
||||
Tablet respects cells reusability feature and it's type-safe. See the Usage section to learn more.
|
||||
Tablet respects cells reusability feature and built with performace in mind. See the Usage section to learn more.
|
||||
|
||||
## Requirements
|
||||
|
||||
|
|
@ -55,7 +68,7 @@ let rowBuilder = TableRowBuilder<User, UITableViewCell>(items: [user1, user2, us
|
|||
data.cell?.detailTextLabel?.text = data.item.isActive ? "Active" : "Inactive"
|
||||
}
|
||||
|
||||
let sectionBuilder = TableSectionBuilder(headerTitle: "Users", rowBuilders: [rowBuilder])
|
||||
let sectionBuilder = TableSectionBuilder(headerTitle: "Users", rows: [rowBuilder])
|
||||
|
||||
director = TableDirector(tableView: tableView)
|
||||
director.appendSections(sectionBuilder)
|
||||
|
|
@ -77,6 +90,10 @@ class MyTableViewCell : UITableViewCell, ConfigurableCell {
|
|||
return "reusable_id"
|
||||
}
|
||||
|
||||
static func estimatedHeight() -> Float {
|
||||
return 255
|
||||
}
|
||||
|
||||
func configureWithItem(item: Item) { // item is user here
|
||||
|
||||
textLabel?.text = item.username
|
||||
|
|
@ -89,11 +106,11 @@ Once you've implemented the protocol, simply use the `TableConfigurableRowBuilde
|
|||
```swift
|
||||
import Tablet
|
||||
|
||||
let rowBuilder = TableConfigurableRowBuilder<User, MyTableViewCell>(estimatedRowHeight: 42)
|
||||
let rowBuilder = TableConfigurableRowBuilder<User, MyTableViewCell>()
|
||||
rowBuilder.appendItems(users)
|
||||
|
||||
director = TableDirector(tableView: tableView)
|
||||
tableDirector.appendSection(TableSectionBuilder(rowBuilders: [rowBuilder]))
|
||||
tableDirector.appendSection(TableSectionBuilder(rows: [rowBuilder]))
|
||||
```
|
||||
|
||||
### Cell actions
|
||||
|
|
@ -134,7 +151,7 @@ And receive this actions with your row builder:
|
|||
```swift
|
||||
import Tablet
|
||||
|
||||
let rowBuilder = TableConfigurableRowBuilder<User, MyTableViewCell>(items: users, id: "reusable_id", estimatedRowHeight: 42)
|
||||
let rowBuilder = TableConfigurableRowBuilder<User, MyTableViewCell>(items: users, id: "reusable_id")
|
||||
.action(.click) { data -> Void in
|
||||
|
||||
}
|
||||
|
|
@ -165,7 +182,7 @@ extension TableDirector {
|
|||
```
|
||||
Catch your action with row builder:
|
||||
```swift
|
||||
let rowBuilder = TableConfigurableRowBuilder<User, MyTableViewCell>(items: users, estimatedRowHeight: 42)
|
||||
let rowBuilder = TableConfigurableRowBuilder<User, MyTableViewCell>(items: users)
|
||||
.action(kTableDirectorDidEndDisplayingCell) { data -> Void in
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'Tablet'
|
||||
s.version = '0.2.6'
|
||||
s.version = '0.3.0'
|
||||
|
||||
s.homepage = 'https://github.com/maxsokolov/tablet'
|
||||
s.summary = 'Powerful type-safe tool for UITableView. Swift 2.0 is required.'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Tablet/Tablet.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:TabletDemo/TabletDemo.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
BIN
Tablet.xcworkspace/xcuserdata/maxsokolov.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
BIN
Tablet.xcworkspace/xcuserdata/maxsokolov.xcuserdatad/UserInterfaceState.xcuserstate
generated
Normal file
Binary file not shown.
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -27,9 +27,9 @@ import Foundation
|
|||
public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
|
||||
|
||||
public private(set) weak var tableView: UITableView!
|
||||
private var sections = [TableSectionBuilder]()
|
||||
public weak var scrollDelegate: UIScrollViewDelegate?
|
||||
|
||||
private var sections = [TableSectionBuilder]()
|
||||
|
||||
public init(tableView: UITableView) {
|
||||
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: "didReceiveAction:", name: kActionPerformedNotificationKey, object: nil)
|
||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: "didReceiveAction:", name: TabletNotifications.CellAction, object: nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
@ -56,24 +56,16 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
- Returns: A touple - (builder, builderItemIndex)
|
||||
*/
|
||||
private func builderAtIndexPath(indexPath: NSIndexPath) -> (RowBuilder, Int) {
|
||||
|
||||
return sections[indexPath.section].builderAtIndex(indexPath.row)!
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
public func invokeAction(action: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> AnyObject? {
|
||||
|
||||
let builder = builderAtIndexPath(indexPath)
|
||||
return builder.0.invokeAction(action, cell: cell, indexPath: indexPath, itemIndex: builder.1, userInfo: nil)
|
||||
}
|
||||
|
||||
internal func didReceiveAction(notification: NSNotification) {
|
||||
|
||||
if let action = notification.object as? Action, indexPath = tableView.indexPathForCell(action.cell) {
|
||||
|
||||
let builder = builderAtIndexPath(indexPath)
|
||||
builder.0.invokeAction(.custom(action.key), cell: action.cell, indexPath: indexPath, itemIndex: builder.1, userInfo: action.userInfo)
|
||||
}
|
||||
}
|
||||
|
||||
public override func respondsToSelector(selector: Selector) -> Bool {
|
||||
return super.respondsToSelector(selector) || scrollDelegate?.respondsToSelector(selector) == true
|
||||
|
|
@ -82,19 +74,28 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
public override func forwardingTargetForSelector(selector: Selector) -> AnyObject? {
|
||||
return scrollDelegate?.respondsToSelector(selector) == true ? scrollDelegate : super.forwardingTargetForSelector(selector)
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
func didReceiveAction(notification: NSNotification) {
|
||||
|
||||
if let action = notification.object as? Action, indexPath = tableView.indexPathForCell(action.cell) {
|
||||
|
||||
let builder = builderAtIndexPath(indexPath)
|
||||
builder.0.invokeAction(.custom(action.key), cell: action.cell, indexPath: indexPath, itemIndex: builder.1, userInfo: notification.userInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension TableDirector {
|
||||
|
||||
|
||||
// MARK: UITableViewDataSource - configuration
|
||||
|
||||
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
|
||||
|
||||
return sections.count
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
||||
return sections[section].numberOfRowsInSection
|
||||
}
|
||||
|
||||
|
|
@ -120,34 +121,28 @@ public extension TableDirector {
|
|||
// MARK: UITableViewDataSource - section setup
|
||||
|
||||
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
|
||||
return sections[section].headerTitle
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
|
||||
return sections[section].footerTitle
|
||||
}
|
||||
|
||||
// MARK: UITableViewDelegate - section setup
|
||||
|
||||
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||
|
||||
return sections[section].headerView
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
||||
|
||||
return sections[section].footerView
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
|
||||
return sections[section].headerHeight
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
|
||||
|
||||
return sections[section].footerHeight
|
||||
}
|
||||
}
|
||||
|
|
@ -157,19 +152,17 @@ public extension TableDirector {
|
|||
// MARK: UITableViewDelegate - actions
|
||||
|
||||
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
|
||||
return builderAtIndexPath(indexPath).0.estimatedRowHeight
|
||||
return CGFloat(builderAtIndexPath(indexPath).0.estimatedRowHeight)
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
|
||||
return invokeAction(.height, cell: nil, indexPath: indexPath) as? CGFloat ?? UITableViewAutomaticDimension
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
|
||||
/*func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
|
||||
|
||||
return invokeAction(.willSelect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? NSIndexPath ?? indexPath
|
||||
}
|
||||
return invokeAction(.willSelect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? NSIndexPath
|
||||
}*/
|
||||
|
||||
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
|
|
@ -183,17 +176,14 @@ public extension TableDirector {
|
|||
}
|
||||
|
||||
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
invokeAction(.deselect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath)
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
invokeAction(.willDisplay, cell: cell, indexPath: indexPath)
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
|
||||
|
||||
return invokeAction(.shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true
|
||||
}
|
||||
}
|
||||
|
|
@ -218,21 +208,17 @@ public extension TableDirector {
|
|||
}
|
||||
|
||||
public func +=(left: TableDirector, right: RowBuilder) {
|
||||
|
||||
left.appendSection(TableSectionBuilder(rowBuilders: [right]))
|
||||
left.appendSection(TableSectionBuilder(rows: [right]))
|
||||
}
|
||||
|
||||
public func +=(left: TableDirector, right: [RowBuilder]) {
|
||||
|
||||
left.appendSection(TableSectionBuilder(rowBuilders: right))
|
||||
left.appendSection(TableSectionBuilder(rows: right))
|
||||
}
|
||||
|
||||
public func +=(left: TableDirector, right: TableSectionBuilder) {
|
||||
|
||||
left.appendSection(right)
|
||||
}
|
||||
|
||||
public func +=(left: TableDirector, right: [TableSectionBuilder]) {
|
||||
|
||||
left.appendSections(right)
|
||||
}
|
||||
|
|
@ -23,13 +23,13 @@ import Foundation
|
|||
|
||||
public typealias ReturnValue = AnyObject?
|
||||
|
||||
internal enum ActionHandler<I, C> {
|
||||
|
||||
enum ActionHandler<I, C> {
|
||||
|
||||
case actionBlock((data: ActionData<I, C>) -> Void)
|
||||
case actionReturnBlock((data: ActionData<I, C>) -> AnyObject?)
|
||||
|
||||
func invoke(data: ActionData<I, C>) -> ReturnValue {
|
||||
|
||||
|
||||
switch (self) {
|
||||
case .actionBlock(let closure):
|
||||
closure(data: data)
|
||||
|
|
@ -40,33 +40,50 @@ internal enum ActionHandler<I, C> {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Responsible for building cells of given type and passing items to them.
|
||||
*/
|
||||
public class TableRowBuilder<I, C where C: UITableViewCell> : RowBuilder {
|
||||
|
||||
private var actions = Dictionary<String, ActionHandler<I, C>>()
|
||||
private var items = [I]()
|
||||
|
||||
public var reusableIdentifier: String
|
||||
public var estimatedRowHeight: CGFloat
|
||||
public class RowBuilder : NSObject {
|
||||
|
||||
public private(set) var reusableIdentifier: String
|
||||
public var numberOfRows: Int {
|
||||
get {
|
||||
return items.count
|
||||
}
|
||||
return 0
|
||||
}
|
||||
public var estimatedRowHeight: Float {
|
||||
return 44
|
||||
}
|
||||
|
||||
public init(item: I, id: String? = nil, estimatedRowHeight: CGFloat = 48) {
|
||||
init(id: String) {
|
||||
reusableIdentifier = id
|
||||
}
|
||||
|
||||
// MARK: internal methods, must be overriden in subclass
|
||||
|
||||
func invokeAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int, userInfo: [NSObject: AnyObject]?) -> AnyObject? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func registerCell(inTableView tableView: UITableView) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Responsible for building cells of given type and passing items to them.
|
||||
*/
|
||||
public class TableRowBuilder<I, C where C: UITableViewCell> : RowBuilder {
|
||||
|
||||
private var actions = Dictionary<String, ActionHandler<I, C>>()
|
||||
private var items = [I]()
|
||||
|
||||
public override var numberOfRows: Int {
|
||||
return items.count
|
||||
}
|
||||
|
||||
public init(item: I, id: String? = nil) {
|
||||
super.init(id: id ?? NSStringFromClass(C).componentsSeparatedByString(".").last ?? "")
|
||||
|
||||
reusableIdentifier = id ?? NSStringFromClass(C).componentsSeparatedByString(".").last ?? ""
|
||||
self.estimatedRowHeight = estimatedRowHeight
|
||||
items.append(item)
|
||||
}
|
||||
|
||||
public init(items: [I]? = nil, id: String? = nil, estimatedRowHeight: CGFloat = 48) {
|
||||
|
||||
reusableIdentifier = id ?? NSStringFromClass(C).componentsSeparatedByString(".").last ?? ""
|
||||
self.estimatedRowHeight = estimatedRowHeight
|
||||
public init(items: [I]? = nil, id: String? = nil) {
|
||||
super.init(id: id ?? NSStringFromClass(C).componentsSeparatedByString(".").last ?? "")
|
||||
|
||||
if items != nil {
|
||||
self.items.appendContentsOf(items!)
|
||||
|
|
@ -74,101 +91,101 @@ public class TableRowBuilder<I, C where C: UITableViewCell> : RowBuilder {
|
|||
}
|
||||
|
||||
// MARK: Chaining actions
|
||||
|
||||
|
||||
public func action(key: String, closure: (data: ActionData<I, C>) -> Void) -> Self {
|
||||
|
||||
|
||||
actions[key] = .actionBlock(closure)
|
||||
return self
|
||||
}
|
||||
|
||||
public func action(actionType: ActionType, closure: (data: ActionData<I, C>) -> Void) -> Self {
|
||||
|
||||
|
||||
actions[actionType.key] = .actionBlock(closure)
|
||||
return self
|
||||
}
|
||||
|
||||
public func action(actionType: ActionType, closure: (data: ActionData<I, C>) -> ReturnValue) -> Self {
|
||||
|
||||
|
||||
actions[actionType.key] = .actionReturnBlock(closure)
|
||||
return self
|
||||
}
|
||||
|
||||
// MARK: Triggers
|
||||
// MARK: Internal
|
||||
|
||||
public func invokeAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int, userInfo: [NSObject: AnyObject]? = nil) -> AnyObject? {
|
||||
|
||||
override func invokeAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int, userInfo: [NSObject: AnyObject]?) -> AnyObject? {
|
||||
|
||||
if let action = actions[actionType.key] {
|
||||
return action.invoke(ActionData(cell: cell as? C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex))
|
||||
return action.invoke(ActionData(cell: cell as? C, indexPath: indexPath, item: items[itemIndex], itemIndex: itemIndex, userInfo: userInfo))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
public func registerCell(inTableView tableView: UITableView) {
|
||||
|
||||
|
||||
override func registerCell(inTableView tableView: UITableView) {
|
||||
|
||||
if tableView.dequeueReusableCellWithIdentifier(reusableIdentifier) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
guard let resource = NSStringFromClass(C).componentsSeparatedByString(".").last else { return }
|
||||
|
||||
|
||||
let bundle = NSBundle(forClass: C.self)
|
||||
|
||||
if let _ = bundle.pathForResource(resource, ofType: "nib") { // existing cell
|
||||
|
||||
|
||||
tableView.registerNib(UINib(nibName: resource, bundle: bundle), forCellReuseIdentifier: reusableIdentifier)
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
tableView.registerClass(C.self, forCellReuseIdentifier: reusableIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Responsible for building configurable cells of given type and passing items to them.
|
||||
*/
|
||||
Responsible for building configurable cells of given type and passing items to them.
|
||||
*/
|
||||
public class TableConfigurableRowBuilder<I, C: ConfigurableCell where C.Item == I, C: UITableViewCell> : TableRowBuilder<I, C> {
|
||||
|
||||
public init(item: I, estimatedRowHeight: CGFloat = 48) {
|
||||
super.init(item: item, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight)
|
||||
|
||||
public override var estimatedRowHeight: Float {
|
||||
return C.estimatedHeight()
|
||||
}
|
||||
|
||||
public init(items: [I]? = nil, estimatedRowHeight: CGFloat = 48) {
|
||||
super.init(items: items, id: C.reusableIdentifier(), estimatedRowHeight: estimatedRowHeight)
|
||||
|
||||
public init(item: I) {
|
||||
super.init(item: item, id: C.reusableIdentifier())
|
||||
}
|
||||
|
||||
public override func invokeAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int, userInfo: [NSObject: AnyObject]? = nil) -> AnyObject? {
|
||||
|
||||
|
||||
public init(items: [I]? = nil) {
|
||||
super.init(items: items, id: C.reusableIdentifier())
|
||||
}
|
||||
|
||||
override func invokeAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int, userInfo: [NSObject: AnyObject]?) -> AnyObject? {
|
||||
|
||||
switch actionType {
|
||||
case .configure:
|
||||
(cell as? C)?.configureWithItem(items[itemIndex])
|
||||
default: break
|
||||
}
|
||||
return super.invokeAction(actionType, cell: cell, indexPath: indexPath, itemIndex: itemIndex)
|
||||
return super.invokeAction(actionType, cell: cell, indexPath: indexPath, itemIndex: itemIndex, userInfo: userInfo)
|
||||
}
|
||||
}
|
||||
|
||||
public extension TableRowBuilder {
|
||||
|
||||
|
||||
// MARK: Items manipulation
|
||||
|
||||
public func appendItems(items: [I]) {
|
||||
|
||||
self.items.appendContentsOf(items)
|
||||
}
|
||||
|
||||
public func clear() {
|
||||
|
||||
items.removeAll()
|
||||
}
|
||||
}
|
||||
|
||||
public func +=<I, C>(left: TableRowBuilder<I, C>, right: I) {
|
||||
|
||||
left.appendItems([right])
|
||||
}
|
||||
|
||||
public func +=<I, C>(left: TableRowBuilder<I, C>, right: [I]) {
|
||||
|
||||
left.appendItems(right)
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ import Foundation
|
|||
*/
|
||||
public class TableSectionBuilder {
|
||||
|
||||
internal weak var tableView: UITableView?
|
||||
weak var tableView: UITableView?
|
||||
private var builders = [RowBuilder]()
|
||||
|
||||
public var headerTitle: String?
|
||||
|
|
@ -38,19 +38,18 @@ public class TableSectionBuilder {
|
|||
|
||||
public var footerView: UIView?
|
||||
public var footerHeight: CGFloat = UITableViewAutomaticDimension
|
||||
|
||||
|
||||
/// A total number of rows in section of each row builder.
|
||||
public var numberOfRowsInSection: Int {
|
||||
|
||||
return builders.reduce(0) { $0 + $1.numberOfRows }
|
||||
}
|
||||
|
||||
public init(headerTitle: String? = nil, footerTitle: String? = nil, rowBuilders: [RowBuilder]? = nil) {
|
||||
public init(headerTitle: String? = nil, footerTitle: String? = nil, rows: [RowBuilder]? = nil) {
|
||||
|
||||
self.headerTitle = headerTitle
|
||||
self.footerTitle = footerTitle
|
||||
|
||||
if let initialRows = rowBuilders {
|
||||
if let initialRows = rows {
|
||||
builders.appendContentsOf(initialRows)
|
||||
}
|
||||
}
|
||||
|
|
@ -63,11 +62,26 @@ public class TableSectionBuilder {
|
|||
self.footerView = footerView
|
||||
self.footerHeight = footerHeight
|
||||
}
|
||||
}
|
||||
|
||||
internal extension TableSectionBuilder {
|
||||
// MARK: Public
|
||||
|
||||
public func clear() {
|
||||
builders.removeAll()
|
||||
}
|
||||
|
||||
internal func builderAtIndex(var index: Int) -> (RowBuilder, Int)? {
|
||||
public func appendRow(row: RowBuilder) {
|
||||
appendRows([row])
|
||||
}
|
||||
|
||||
public func appendRows(rowBuilders: [RowBuilder]) {
|
||||
|
||||
if let tableView = tableView { rowBuilders.forEach { $0.registerCell(inTableView: tableView) } }
|
||||
builders.appendContentsOf(rowBuilders)
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
func builderAtIndex(var index: Int) -> (RowBuilder, Int)? {
|
||||
|
||||
for builder in builders {
|
||||
if index < builder.numberOfRows {
|
||||
|
|
@ -78,38 +92,18 @@ internal extension TableSectionBuilder {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func willMoveToDirector(tableView: UITableView) {
|
||||
|
||||
internal func willMoveToDirector(tableView: UITableView) {
|
||||
self.tableView = tableView
|
||||
self.builders.forEach { $0.registerCell(inTableView: tableView) }
|
||||
}
|
||||
}
|
||||
|
||||
public extension TableSectionBuilder {
|
||||
|
||||
public func clear() {
|
||||
|
||||
builders.removeAll()
|
||||
}
|
||||
|
||||
public func appendRowBuilder(rowBuilder: RowBuilder) {
|
||||
|
||||
appendRowBuilders([rowBuilder])
|
||||
}
|
||||
|
||||
public func appendRowBuilders(rowBuilders: [RowBuilder]) {
|
||||
|
||||
if let tableView = tableView { rowBuilders.forEach { $0.registerCell(inTableView: tableView) } }
|
||||
builders.appendContentsOf(rowBuilders)
|
||||
}
|
||||
}
|
||||
|
||||
public func +=(left: TableSectionBuilder, right: RowBuilder) {
|
||||
|
||||
left.appendRowBuilder(right)
|
||||
left.appendRow(right)
|
||||
}
|
||||
|
||||
public func +=(left: TableSectionBuilder, right: [RowBuilder]) {
|
||||
|
||||
left.appendRowBuilders(right)
|
||||
left.appendRows(right)
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// 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 Foundation;
|
||||
|
||||
FOUNDATION_EXPORT double TabletVersionNumber;
|
||||
FOUNDATION_EXPORT const unsigned char TabletVersionString[];
|
||||
|
|
@ -21,7 +21,9 @@
|
|||
import UIKit
|
||||
import Foundation
|
||||
|
||||
internal let kActionPerformedNotificationKey = "_action"
|
||||
struct TabletNotifications {
|
||||
static let CellAction = "TabletNotificationsCellAction"
|
||||
}
|
||||
|
||||
/**
|
||||
The actions that Tablet provides.
|
||||
|
|
@ -55,13 +57,15 @@ public class ActionData<I, C> {
|
|||
public let item: I
|
||||
public let itemIndex: Int
|
||||
public let indexPath: NSIndexPath
|
||||
|
||||
init(cell: C?, indexPath: NSIndexPath, item: I, itemIndex: Int) {
|
||||
|
||||
public let userInfo: [NSObject: AnyObject]?
|
||||
|
||||
init(cell: C?, indexPath: NSIndexPath, item: I, itemIndex: Int, userInfo: [NSObject: AnyObject]?) {
|
||||
|
||||
self.cell = cell
|
||||
self.indexPath = indexPath
|
||||
self.item = item
|
||||
self.itemIndex = itemIndex
|
||||
self.userInfo = userInfo
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,8 +92,7 @@ public class Action {
|
|||
}
|
||||
|
||||
public func invoke() {
|
||||
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(kActionPerformedNotificationKey, object: self)
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(TabletNotifications.CellAction, object: self, userInfo: userInfo)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,27 +105,13 @@ public protocol ConfigurableCell {
|
|||
typealias Item
|
||||
|
||||
static func reusableIdentifier() -> String
|
||||
static func estimatedHeight() -> Float
|
||||
func configureWithItem(item: Item)
|
||||
}
|
||||
|
||||
public extension ConfigurableCell where Self: UITableViewCell {
|
||||
|
||||
static func reusableIdentifier() -> String {
|
||||
|
||||
return NSStringFromClass(self).componentsSeparatedByString(".").last ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
A protocol that every row builder should follow.
|
||||
A certain section can only works with row builders that respect this protocol.
|
||||
*/
|
||||
public protocol RowBuilder {
|
||||
|
||||
var numberOfRows: Int { get }
|
||||
var reusableIdentifier: String { get }
|
||||
var estimatedRowHeight: CGFloat { get }
|
||||
|
||||
func registerCell(inTableView tableView: UITableView)
|
||||
func invokeAction(actionType: ActionType, cell: UITableViewCell?, indexPath: NSIndexPath, itemIndex: Int, userInfo: [NSObject: AnyObject]?) -> AnyObject?
|
||||
}
|
||||
|
|
@ -0,0 +1,423 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
DAC2D6741C9D743D009E9C19 /* Tablet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAC2D6691C9D743D009E9C19 /* Tablet.framework */; };
|
||||
DAC2D6871C9D7517009E9C19 /* Tablet.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC2D6851C9D7517009E9C19 /* Tablet.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
DAC2D6901C9D799E009E9C19 /* TableDirector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D68C1C9D799E009E9C19 /* TableDirector.swift */; };
|
||||
DAC2D6911C9D799E009E9C19 /* TableRowBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D68D1C9D799E009E9C19 /* TableRowBuilder.swift */; };
|
||||
DAC2D6921C9D799E009E9C19 /* TableSectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D68E1C9D799E009E9C19 /* TableSectionBuilder.swift */; };
|
||||
DAC2D6931C9D799E009E9C19 /* Tablet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D68F1C9D799E009E9C19 /* Tablet.swift */; };
|
||||
DAC2D6991C9D7A3F009E9C19 /* TabletTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D6961C9D7A3B009E9C19 /* TabletTests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
DAC2D6751C9D743D009E9C19 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DAC2D6601C9D743D009E9C19 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DAC2D6681C9D743D009E9C19;
|
||||
remoteInfo = Tablet;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
DAC2D6691C9D743D009E9C19 /* Tablet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Tablet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAC2D6731C9D743D009E9C19 /* TabletTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TabletTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAC2D6841C9D7517009E9C19 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
DAC2D6851C9D7517009E9C19 /* Tablet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tablet.h; sourceTree = "<group>"; };
|
||||
DAC2D68C1C9D799E009E9C19 /* TableDirector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableDirector.swift; sourceTree = "<group>"; };
|
||||
DAC2D68D1C9D799E009E9C19 /* TableRowBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRowBuilder.swift; sourceTree = "<group>"; };
|
||||
DAC2D68E1C9D799E009E9C19 /* TableSectionBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableSectionBuilder.swift; sourceTree = "<group>"; };
|
||||
DAC2D68F1C9D799E009E9C19 /* Tablet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tablet.swift; sourceTree = "<group>"; };
|
||||
DAC2D6951C9D7A3B009E9C19 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
DAC2D6961C9D7A3B009E9C19 /* TabletTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabletTests.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
DAC2D6651C9D743D009E9C19 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DAC2D6701C9D743D009E9C19 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAC2D6741C9D743D009E9C19 /* Tablet.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
DAC2D65F1C9D743D009E9C19 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D68B1C9D7990009E9C19 /* Classes */,
|
||||
DAC2D6941C9D7A03009E9C19 /* Tests */,
|
||||
DAC2D6831C9D74EE009E9C19 /* Supporting Files */,
|
||||
DAC2D66A1C9D743D009E9C19 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D66A1C9D743D009E9C19 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D6691C9D743D009E9C19 /* Tablet.framework */,
|
||||
DAC2D6731C9D743D009E9C19 /* TabletTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D6831C9D74EE009E9C19 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D6841C9D7517009E9C19 /* Info.plist */,
|
||||
DAC2D6851C9D7517009E9C19 /* Tablet.h */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D68B1C9D7990009E9C19 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D68F1C9D799E009E9C19 /* Tablet.swift */,
|
||||
DAC2D68C1C9D799E009E9C19 /* TableDirector.swift */,
|
||||
DAC2D68D1C9D799E009E9C19 /* TableRowBuilder.swift */,
|
||||
DAC2D68E1C9D799E009E9C19 /* TableSectionBuilder.swift */,
|
||||
);
|
||||
name = Classes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D6941C9D7A03009E9C19 /* Tests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D6951C9D7A3B009E9C19 /* Info.plist */,
|
||||
DAC2D6961C9D7A3B009E9C19 /* TabletTests.swift */,
|
||||
);
|
||||
name = Tests;
|
||||
path = ../Tests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
DAC2D6661C9D743D009E9C19 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAC2D6871C9D7517009E9C19 /* Tablet.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
DAC2D6681C9D743D009E9C19 /* Tablet */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DAC2D67D1C9D743D009E9C19 /* Build configuration list for PBXNativeTarget "Tablet" */;
|
||||
buildPhases = (
|
||||
DAC2D6641C9D743D009E9C19 /* Sources */,
|
||||
DAC2D6651C9D743D009E9C19 /* Frameworks */,
|
||||
DAC2D6661C9D743D009E9C19 /* Headers */,
|
||||
DAC2D6671C9D743D009E9C19 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Tablet;
|
||||
productName = Tablet;
|
||||
productReference = DAC2D6691C9D743D009E9C19 /* Tablet.framework */;
|
||||
productType = "com.apple.product-type.framework";
|
||||
};
|
||||
DAC2D6721C9D743D009E9C19 /* TabletTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DAC2D6801C9D743D009E9C19 /* Build configuration list for PBXNativeTarget "TabletTests" */;
|
||||
buildPhases = (
|
||||
DAC2D66F1C9D743D009E9C19 /* Sources */,
|
||||
DAC2D6701C9D743D009E9C19 /* Frameworks */,
|
||||
DAC2D6711C9D743D009E9C19 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DAC2D6761C9D743D009E9C19 /* PBXTargetDependency */,
|
||||
);
|
||||
name = TabletTests;
|
||||
productName = TabletTests;
|
||||
productReference = DAC2D6731C9D743D009E9C19 /* TabletTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
DAC2D6601C9D743D009E9C19 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0720;
|
||||
LastUpgradeCheck = 0720;
|
||||
ORGANIZATIONNAME = Tablet;
|
||||
TargetAttributes = {
|
||||
DAC2D6681C9D743D009E9C19 = {
|
||||
CreatedOnToolsVersion = 7.2;
|
||||
};
|
||||
DAC2D6721C9D743D009E9C19 = {
|
||||
CreatedOnToolsVersion = 7.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = DAC2D6631C9D743D009E9C19 /* Build configuration list for PBXProject "Tablet" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = DAC2D65F1C9D743D009E9C19;
|
||||
productRefGroup = DAC2D66A1C9D743D009E9C19 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
DAC2D6681C9D743D009E9C19 /* Tablet */,
|
||||
DAC2D6721C9D743D009E9C19 /* TabletTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
DAC2D6671C9D743D009E9C19 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DAC2D6711C9D743D009E9C19 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
DAC2D6641C9D743D009E9C19 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAC2D6901C9D799E009E9C19 /* TableDirector.swift in Sources */,
|
||||
DAC2D6921C9D799E009E9C19 /* TableSectionBuilder.swift in Sources */,
|
||||
DAC2D6911C9D799E009E9C19 /* TableRowBuilder.swift in Sources */,
|
||||
DAC2D6931C9D799E009E9C19 /* Tablet.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DAC2D66F1C9D743D009E9C19 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAC2D6991C9D7A3F009E9C19 /* TabletTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
DAC2D6761C9D743D009E9C19 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DAC2D6681C9D743D009E9C19 /* Tablet */;
|
||||
targetProxy = DAC2D6751C9D743D009E9C19 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
DAC2D67B1C9D743D009E9C19 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DAC2D67C1C9D743D009E9C19 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DAC2D67E1C9D743D009E9C19 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.tablet;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DAC2D67F1C9D743D009E9C19 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.tablet;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DAC2D6811C9D743D009E9C19 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = ../Tests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.tablet.TabletTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DAC2D6821C9D743D009E9C19 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
INFOPLIST_FILE = ../Tests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.tablet.TabletTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
DAC2D6631C9D743D009E9C19 /* Build configuration list for PBXProject "Tablet" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DAC2D67B1C9D743D009E9C19 /* Debug */,
|
||||
DAC2D67C1C9D743D009E9C19 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
DAC2D67D1C9D743D009E9C19 /* Build configuration list for PBXNativeTarget "Tablet" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DAC2D67E1C9D743D009E9C19 /* Debug */,
|
||||
DAC2D67F1C9D743D009E9C19 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
DAC2D6801C9D743D009E9C19 /* Build configuration list for PBXNativeTarget "TabletTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DAC2D6811C9D743D009E9C19 /* Debug */,
|
||||
DAC2D6821C9D743D009E9C19 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = DAC2D6601C9D743D009E9C19 /* Project object */;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:Tablet.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
Binary file not shown.
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DAC2D6681C9D743D009E9C19"
|
||||
BuildableName = "Tablet.framework"
|
||||
BlueprintName = "Tablet"
|
||||
ReferencedContainer = "container:Tablet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DAC2D6721C9D743D009E9C19"
|
||||
BuildableName = "TabletTests.xctest"
|
||||
BlueprintName = "TabletTests"
|
||||
ReferencedContainer = "container:Tablet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DAC2D6681C9D743D009E9C19"
|
||||
BuildableName = "Tablet.framework"
|
||||
BlueprintName = "Tablet"
|
||||
ReferencedContainer = "container:Tablet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<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 = "DAC2D6681C9D743D009E9C19"
|
||||
BuildableName = "Tablet.framework"
|
||||
BlueprintName = "Tablet"
|
||||
ReferencedContainer = "container:Tablet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DAC2D6681C9D743D009E9C19"
|
||||
BuildableName = "Tablet.framework"
|
||||
BlueprintName = "Tablet"
|
||||
ReferencedContainer = "container:Tablet.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Bucket
|
||||
type = "1"
|
||||
version = "2.0">
|
||||
</Bucket>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>Tablet.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
<key>DAC2D6681C9D743D009E9C19</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>DAC2D6721C9D743D009E9C19</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// MainViewController.swift
|
||||
// TabletDemo
|
||||
//
|
||||
// Created by Max Sokolov on 19/03/16.
|
||||
// Copyright © 2016 Tablet. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Tablet
|
||||
|
||||
class MainViewController : UITableViewController {
|
||||
|
||||
var tableDirector: TableDirector!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tableDirector = TableDirector(tableView: tableView)
|
||||
|
||||
tableDirector += TableRowBuilder<Int, UITableViewCell>(items: [1, 2, 3, 4], id: "cell")
|
||||
.action(.configure) { data -> Void in
|
||||
|
||||
data.cell?.accessoryType = .DisclosureIndicator
|
||||
data.cell?.textLabel?.text = "\(data.item)"
|
||||
}
|
||||
.action(.click) { data -> Void in
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
|
|
@ -16,7 +16,6 @@
|
|||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="dOU-ON-YYD">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Main View Controller-->
|
||||
<scene sceneID="oP2-EZ-N5W">
|
||||
<objects>
|
||||
<tableViewController id="ZyD-Ww-nfe" customClass="MainViewController" customModule="TabletDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="xii-6e-J4f">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" id="eQJ-7O-k03">
|
||||
<rect key="frame" x="0.0" y="92" width="600" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="eQJ-7O-k03" id="Ufi-z4-pLt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="ZyD-Ww-nfe" id="dup-HU-FfF"/>
|
||||
<outlet property="delegate" destination="ZyD-Ww-nfe" id="bRX-uu-KTX"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" id="6ba-xC-prc"/>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="uxV-eY-exN" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1074" y="287"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="Nb3-Yi-ik8">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="dOU-ON-YYD" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="Ngx-L8-cbs">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="ZyD-Ww-nfe" kind="relationship" relationship="rootViewController" id="vRk-x4-ylh"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="1px-T5-UXL" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="334" y="287"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
|
@ -7,39 +7,21 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
508B71841BF48DD300272920 /* TableSectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508B71831BF48DD300272920 /* TableSectionBuilder.swift */; };
|
||||
508B71861BF48E0D00272920 /* TableRowBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508B71851BF48E0D00272920 /* TableRowBuilder.swift */; };
|
||||
DA1BCD0F1BF5472C00CC0479 /* TableDirector.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA1BCD0E1BF5472C00CC0479 /* TableDirector.swift */; };
|
||||
DA1BCD111BF7388C00CC0479 /* CustomTableActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA1BCD101BF7388C00CC0479 /* CustomTableActions.swift */; };
|
||||
DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */; };
|
||||
DAB7EB2D1BEF787300D2AD5E /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */; };
|
||||
DAB7EB301BEF787300D2AD5E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */; };
|
||||
DAB7EB321BEF787300D2AD5E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DAB7EB311BEF787300D2AD5E /* Assets.xcassets */; };
|
||||
DAB7EB351BEF787300D2AD5E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */; };
|
||||
DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */; };
|
||||
DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */; };
|
||||
DAED08F11C14DE7E006C04D8 /* MyTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAED08F01C14DE7E006C04D8 /* MyTableViewCell.swift */; };
|
||||
DAF003961C14DC0C0028C3D6 /* MyNibTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAF003951C14DC0C0028C3D6 /* MyNibTableViewCell.swift */; };
|
||||
DAF003981C14DC250028C3D6 /* MyNibTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DAF003971C14DC250028C3D6 /* MyNibTableViewCell.xib */; };
|
||||
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 */; };
|
||||
DAC2D5D41C9D3118009E9C19 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DAC2D5D31C9D3118009E9C19 /* MainViewController.swift */; };
|
||||
DAC2D69C1C9E75E3009E9C19 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DAC2D69B1C9E75E3009E9C19 /* Assets.xcassets */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
508B71831BF48DD300272920 /* TableSectionBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableSectionBuilder.swift; sourceTree = "<group>"; };
|
||||
508B71851BF48E0D00272920 /* TableRowBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableRowBuilder.swift; sourceTree = "<group>"; };
|
||||
DA1BCD0E1BF5472C00CC0479 /* TableDirector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableDirector.swift; sourceTree = "<group>"; };
|
||||
DA1BCD101BF7388C00CC0479 /* CustomTableActions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomTableActions.swift; sourceTree = "<group>"; };
|
||||
DAB7EB271BEF787300D2AD5E /* TabletDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TabletDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
DAB7EB2F1BEF787300D2AD5E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
DAB7EB311BEF787300D2AD5E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
DAB7EB341BEF787300D2AD5E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
DAB7EB361BEF787300D2AD5E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tablet.swift; sourceTree = "<group>"; };
|
||||
DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurableTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DAED08F01C14DE7E006C04D8 /* MyTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DAF003951C14DC0C0028C3D6 /* MyNibTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyNibTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DAF003971C14DC250028C3D6 /* MyNibTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MyNibTableViewCell.xib; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
DAC2D5CE1C9D30A7009E9C19 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
DAC2D5D31C9D3118009E9C19 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
|
||||
DAC2D69B1C9E75E3009E9C19 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
DAC2D69D1C9E78B5009E9C19 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -56,8 +38,8 @@
|
|||
DAB7EB1E1BEF787300D2AD5E = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7EB3C1BEF789500D2AD5E /* Tablet */,
|
||||
DAB7EB291BEF787300D2AD5E /* TabletDemo */,
|
||||
DAC2D5C61C9D2FE5009E9C19 /* Classes */,
|
||||
DAC2D5CB1C9D3058009E9C19 /* Resources */,
|
||||
DAB7EB281BEF787300D2AD5E /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -70,34 +52,72 @@
|
|||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7EB291BEF787300D2AD5E /* TabletDemo */ = {
|
||||
DAC2D5C61C9D2FE5009E9C19 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7EB2A1BEF787300D2AD5E /* AppDelegate.swift */,
|
||||
DAB7EB2C1BEF787300D2AD5E /* ViewController.swift */,
|
||||
DAB7EB3F1BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift */,
|
||||
DA1BCD101BF7388C00CC0479 /* CustomTableActions.swift */,
|
||||
DAF003951C14DC0C0028C3D6 /* MyNibTableViewCell.swift */,
|
||||
DAF003971C14DC250028C3D6 /* MyNibTableViewCell.xib */,
|
||||
DAED08F01C14DE7E006C04D8 /* MyTableViewCell.swift */,
|
||||
DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */,
|
||||
DAB7EB311BEF787300D2AD5E /* Assets.xcassets */,
|
||||
DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */,
|
||||
DAB7EB361BEF787300D2AD5E /* Info.plist */,
|
||||
DAC2D5C81C9D3014009E9C19 /* Application */,
|
||||
DAC2D5C71C9D3005009E9C19 /* Presentation */,
|
||||
);
|
||||
path = TabletDemo;
|
||||
path = Classes;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7EB3C1BEF789500D2AD5E /* Tablet */ = {
|
||||
DAC2D5C71C9D3005009E9C19 /* Presentation */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAB7EB3D1BEF78A400D2AD5E /* Tablet.swift */,
|
||||
DA1BCD0E1BF5472C00CC0479 /* TableDirector.swift */,
|
||||
508B71851BF48E0D00272920 /* TableRowBuilder.swift */,
|
||||
508B71831BF48DD300272920 /* TableSectionBuilder.swift */,
|
||||
DAC2D5D11C9D30D8009E9C19 /* Main */,
|
||||
);
|
||||
name = Tablet;
|
||||
path = ../Tablet;
|
||||
path = Presentation;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D5C81C9D3014009E9C19 /* Application */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D5C91C9D303E009E9C19 /* AppDelegate.swift */,
|
||||
);
|
||||
path = Application;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D5CB1C9D3058009E9C19 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D69D1C9E78B5009E9C19 /* Info.plist */,
|
||||
DAC2D69A1C9E75BE009E9C19 /* Assets */,
|
||||
DAC2D5CC1C9D306C009E9C19 /* Storyboards */,
|
||||
);
|
||||
path = Resources;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D5CC1C9D306C009E9C19 /* Storyboards */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D5CD1C9D30A7009E9C19 /* Main.storyboard */,
|
||||
DAC2D5CE1C9D30A7009E9C19 /* LaunchScreen.storyboard */,
|
||||
);
|
||||
path = Storyboards;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D5D11C9D30D8009E9C19 /* Main */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D5D21C9D30E4009E9C19 /* ViewControllers */,
|
||||
);
|
||||
path = Main;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D5D21C9D30E4009E9C19 /* ViewControllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D5D31C9D3118009E9C19 /* MainViewController.swift */,
|
||||
);
|
||||
path = ViewControllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAC2D69A1C9E75BE009E9C19 /* Assets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DAC2D69B1C9E75E3009E9C19 /* Assets.xcassets */,
|
||||
);
|
||||
path = Assets;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
|
@ -126,6 +146,7 @@
|
|||
DAB7EB1F1BEF787300D2AD5E /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0720;
|
||||
LastUpgradeCheck = 0700;
|
||||
ORGANIZATIONNAME = Tablet;
|
||||
TargetAttributes = {
|
||||
|
|
@ -158,10 +179,9 @@
|
|||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DAB7EB351BEF787300D2AD5E /* LaunchScreen.storyboard in Resources */,
|
||||
DAF003981C14DC250028C3D6 /* MyNibTableViewCell.xib in Resources */,
|
||||
DAB7EB321BEF787300D2AD5E /* Assets.xcassets in Resources */,
|
||||
DAB7EB301BEF787300D2AD5E /* Main.storyboard in Resources */,
|
||||
DAC2D5CF1C9D30A7009E9C19 /* Main.storyboard in Resources */,
|
||||
DAC2D5D01C9D30A7009E9C19 /* LaunchScreen.storyboard in Resources */,
|
||||
DAC2D69C1C9E75E3009E9C19 /* Assets.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -172,40 +192,13 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
508B71841BF48DD300272920 /* TableSectionBuilder.swift in Sources */,
|
||||
DAB7EB2D1BEF787300D2AD5E /* ViewController.swift in Sources */,
|
||||
DAB7EB3E1BEF78A400D2AD5E /* Tablet.swift in Sources */,
|
||||
DAED08F11C14DE7E006C04D8 /* MyTableViewCell.swift in Sources */,
|
||||
DAF003961C14DC0C0028C3D6 /* MyNibTableViewCell.swift in Sources */,
|
||||
508B71861BF48E0D00272920 /* TableRowBuilder.swift in Sources */,
|
||||
DA1BCD0F1BF5472C00CC0479 /* TableDirector.swift in Sources */,
|
||||
DAB7EB401BEFD07E00D2AD5E /* ConfigurableTableViewCell.swift in Sources */,
|
||||
DAB7EB2B1BEF787300D2AD5E /* AppDelegate.swift in Sources */,
|
||||
DA1BCD111BF7388C00CC0479 /* CustomTableActions.swift in Sources */,
|
||||
DAC2D5D41C9D3118009E9C19 /* MainViewController.swift in Sources */,
|
||||
DAC2D5CA1C9D303E009E9C19 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
DAB7EB2E1BEF787300D2AD5E /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
DAB7EB2F1BEF787300D2AD5E /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DAB7EB331BEF787300D2AD5E /* LaunchScreen.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
DAB7EB341BEF787300D2AD5E /* Base */,
|
||||
);
|
||||
name = LaunchScreen.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
DAB7EB371BEF787300D2AD5E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
|
|
@ -294,10 +287,10 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
INFOPLIST_FILE = TabletDemo/Info.plist;
|
||||
INFOPLIST_FILE = Resources/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.TabletDemo;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.tablet;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
};
|
||||
|
|
@ -309,10 +302,10 @@
|
|||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
INFOPLIST_FILE = TabletDemo/Info.plist;
|
||||
INFOPLIST_FILE = Resources/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.TabletDemo;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablet.tablet;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
};
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -28,6 +28,16 @@
|
|||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DAC2D5DB1C9D6433009E9C19"
|
||||
BuildableName = "TabletTests.xctest"
|
||||
BlueprintName = "TabletTests"
|
||||
ReferencedContainer = "container:TabletDemo.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@
|
|||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>DAC2D5DB1C9D6433009E9C19</key>
|
||||
<dict>
|
||||
<key>primary</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="jN2-c3-xf5">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="TabletDemo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="ovi-uI-31e">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<animations/>
|
||||
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" textLabel="Rrx-qY-GXL" style="IBUITableViewCellStyleDefault" id="MhM-yS-XTS">
|
||||
<rect key="frame" x="0.0" y="114" width="600" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="MhM-yS-XTS" id="1uR-sU-VS9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Rrx-qY-GXL">
|
||||
<rect key="frame" x="15" y="0.0" width="570" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<animations/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<animations/>
|
||||
</tableViewCellContentView>
|
||||
<animations/>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ConfigurableTableViewCell" id="GPe-Vu-z5d" customClass="ConfigurableTableViewCell" customModule="TabletDemo" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="158" width="600" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="GPe-Vu-z5d" id="GMV-qL-pTv">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="C3u-xz-sbM">
|
||||
<rect key="frame" x="14" y="5" width="70" height="34"/>
|
||||
<animations/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="70" id="MSu-D8-6BO"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Button">
|
||||
<color key="titleColor" red="0.090196078430000007" green="0.3411764706" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="buttonClicked:" destination="GPe-Vu-z5d" eventType="touchUpInside" id="IbC-qw-alO"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wWp-hU-I3e">
|
||||
<rect key="frame" x="92" y="12" width="498" height="21"/>
|
||||
<animations/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<animations/>
|
||||
<constraints>
|
||||
<constraint firstItem="C3u-xz-sbM" firstAttribute="leading" secondItem="GMV-qL-pTv" secondAttribute="leading" constant="14" id="6j5-PX-P9O"/>
|
||||
<constraint firstItem="C3u-xz-sbM" firstAttribute="centerY" secondItem="GMV-qL-pTv" secondAttribute="centerY" id="OU7-rr-jUL"/>
|
||||
<constraint firstItem="wWp-hU-I3e" firstAttribute="top" secondItem="GMV-qL-pTv" secondAttribute="top" constant="12" id="azl-YD-xyA"/>
|
||||
<constraint firstItem="wWp-hU-I3e" firstAttribute="leading" secondItem="C3u-xz-sbM" secondAttribute="trailing" constant="8" id="tDZ-be-hlD"/>
|
||||
<constraint firstAttribute="bottom" secondItem="wWp-hU-I3e" secondAttribute="bottom" constant="10" id="w4b-rY-Vf2"/>
|
||||
<constraint firstAttribute="trailing" secondItem="wWp-hU-I3e" secondAttribute="trailing" constant="10" id="wlJ-Ga-0f7"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<animations/>
|
||||
<connections>
|
||||
<outlet property="button" destination="C3u-xz-sbM" id="7KC-FU-lBA"/>
|
||||
<outlet property="contentLabel" destination="wWp-hU-I3e" id="uo4-ez-ea8"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<animations/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="ovi-uI-31e" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" id="J1O-uy-ywm"/>
|
||||
<constraint firstItem="ovi-uI-31e" firstAttribute="leading" secondItem="8bC-Xf-vdC" secondAttribute="leading" id="N0t-Cn-F6e"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="ovi-uI-31e" secondAttribute="bottom" id="hgJ-9n-Rwk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ovi-uI-31e" secondAttribute="trailing" id="wbG-7U-YPc"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="8uO-wD-KyX"/>
|
||||
<connections>
|
||||
<outlet property="tableView" destination="ovi-uI-31e" id="zpd-iM-qe3"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="1185" y="-317"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="2aE-PW-F7u">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="jN2-c3-xf5" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="4L0-SI-HVz">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="N0v-UF-dbb"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="jlp-Hv-yz1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="444" y="-317"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
//
|
||||
// ConfigurableTableViewCell.swift
|
||||
// TabletDemo
|
||||
//
|
||||
// Created by Max Sokolov on 08/11/15.
|
||||
// Copyright © 2015 Tablet. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
let kConfigurableTableViewCellButtonClickedAction = "button_clicked"
|
||||
|
||||
class ConfigurableTableViewCell: UITableViewCell, ConfigurableCell {
|
||||
|
||||
typealias Item = String
|
||||
|
||||
@IBOutlet weak var button: UIButton!
|
||||
@IBOutlet weak var contentLabel: UILabel!
|
||||
|
||||
static func reusableIdentifier() -> String {
|
||||
|
||||
return "ConfigurableTableViewCell"
|
||||
}
|
||||
|
||||
func configureWithItem(item: Item) {
|
||||
|
||||
button.setTitle("Button \(item)", forState: .Normal)
|
||||
}
|
||||
|
||||
@IBAction func buttonClicked(sender: UIButton) {
|
||||
|
||||
Action(key: kConfigurableTableViewCellButtonClickedAction, sender: self).invoke()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// CustomTableActions.swift
|
||||
// TabletDemo
|
||||
//
|
||||
// Created by Max Sokolov on 14/11/15.
|
||||
// Copyright © 2015 Tablet. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Foundation
|
||||
|
||||
let kTableDirectorDidEndDisplayingCell = "enddisplaycell"
|
||||
|
||||
extension TableDirector {
|
||||
|
||||
public func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
|
||||
|
||||
invokeAction(.custom(kTableDirectorDidEndDisplayingCell), cell: cell, indexPath: indexPath)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
//
|
||||
// MyNibTableViewCell.swift
|
||||
// TabletDemo
|
||||
//
|
||||
// Created by Max Sokolov on 07/12/15.
|
||||
// Copyright © 2015 Tablet. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
class MyNibTableViewCell : UITableViewCell {
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="9060" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9051"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="MyNibTableViewCell" id="ien-1l-Zfq" customClass="MyNibTableViewCell" customModule="TabletDemo" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ien-1l-Zfq" id="Ddg-Z7-Dq5">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<animations/>
|
||||
</tableViewCellContentView>
|
||||
<animations/>
|
||||
<color key="backgroundColor" red="1" green="0.54996175169999995" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<point key="canvasLocation" x="521" y="285"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
//
|
||||
// MyTableViewCell.swift
|
||||
// TabletDemo
|
||||
//
|
||||
// Created by Max Sokolov on 07/12/15.
|
||||
// Copyright © 2015 Tablet. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
class MyTableViewCell : UITableViewCell {
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
backgroundColor = UIColor.redColor()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
//
|
||||
// ViewController.swift
|
||||
// TabletDemo
|
||||
//
|
||||
// Created by Max Sokolov on 08/11/15.
|
||||
// Copyright © 2015 Tablet. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ViewController: UIViewController, UIScrollViewDelegate {
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
var tableDirector: TableDirector!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
tableDirector = TableDirector(tableView: tableView)
|
||||
tableDirector.scrollDelegate = self
|
||||
|
||||
let rowBuilder = TableRowBuilder<Int, UITableViewCell>(items: [1, 2, 3, 4], id: "cell", estimatedRowHeight: 44)
|
||||
.action(.configure) { data in
|
||||
|
||||
data.cell?.textLabel?.text = "\(data.item)"
|
||||
}
|
||||
.action(.shouldHighlight) { data in
|
||||
|
||||
return false
|
||||
}
|
||||
.action(kTableDirectorDidEndDisplayingCell) { data -> Void in
|
||||
|
||||
print("end display: \(data.indexPath)")
|
||||
}
|
||||
|
||||
|
||||
let configurableRowBuilder = TableConfigurableRowBuilder<String, ConfigurableTableViewCell>(items: ["5", "6", "7", "8"], estimatedRowHeight: 300)
|
||||
.action(.click) { data -> Void in
|
||||
|
||||
print("click action indexPath: \(data.indexPath), item: \(data.item)")
|
||||
}
|
||||
.action(kConfigurableTableViewCellButtonClickedAction) { data -> Void in
|
||||
|
||||
print("custom action indexPath: \(data.indexPath), item: \(data.item)")
|
||||
}
|
||||
.action(.height) { data -> ReturnValue in
|
||||
|
||||
if data.item == "5" {
|
||||
return 70
|
||||
}
|
||||
return nil
|
||||
}
|
||||
.action(.configure) { (data) -> Void in
|
||||
|
||||
data.cell!.contentLabel.text = "Tablet 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."
|
||||
}
|
||||
|
||||
let myRowBuilder = TableRowBuilder<Int, MyTableViewCell>(item: 0, id: "cellll", estimatedRowHeight: 44)
|
||||
|
||||
let sectionBuilder = TableSectionBuilder(headerTitle: "Tablet", footerTitle: "Deal with table view like a boss.", rowBuilders: [rowBuilder, configurableRowBuilder, myRowBuilder])
|
||||
|
||||
tableDirector += sectionBuilder
|
||||
|
||||
sectionBuilder.appendRowBuilder(TableRowBuilder<Int, MyNibTableViewCell>(item: 0, estimatedRowHeight: 44))
|
||||
}
|
||||
|
||||
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
|
||||
print("begin dragging")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
//
|
||||
// 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 XCTest
|
||||
import Tablet
|
||||
|
||||
class TestController: UITableViewController {
|
||||
|
||||
var tableDirector: TableDirector!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableDirector = TableDirector(tableView: tableView)
|
||||
}
|
||||
}
|
||||
|
||||
struct TestData {
|
||||
|
||||
let title: String
|
||||
}
|
||||
|
||||
struct TestTableViewCellOptions {
|
||||
|
||||
static let ReusableIdentifier: String = "ReusableIdentifier"
|
||||
static let CellAction: String = "CellAction"
|
||||
static let CellActionUserInfoKey: String = "CellActionUserInfoKey"
|
||||
static let CellActionUserInfoValue: String = "CellActionUserInfoValue"
|
||||
static let EstimatedHeight: Float = 255
|
||||
}
|
||||
|
||||
class TestTableViewCell: UITableViewCell, ConfigurableCell {
|
||||
|
||||
typealias Item = TestData
|
||||
|
||||
static func reusableIdentifier() -> String {
|
||||
return TestTableViewCellOptions.ReusableIdentifier
|
||||
}
|
||||
|
||||
static func estimatedHeight() -> Float {
|
||||
return TestTableViewCellOptions.EstimatedHeight
|
||||
}
|
||||
|
||||
func configureWithItem(item: Item) {
|
||||
textLabel?.text = item.title
|
||||
}
|
||||
|
||||
func raiseAction() {
|
||||
Action(key: TestTableViewCellOptions.CellAction, sender: self, userInfo: [TestTableViewCellOptions.CellActionUserInfoKey: TestTableViewCellOptions.CellActionUserInfoValue]).invoke()
|
||||
}
|
||||
}
|
||||
|
||||
class TabletTests: XCTestCase {
|
||||
|
||||
var testController: TestController!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
testController = TestController()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
|
||||
testController = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testTableDirectorHasTableView() {
|
||||
|
||||
XCTAssertNotNil(testController.tableView, "TestController should have table view")
|
||||
XCTAssertNotNil(testController.tableDirector, "TestController should have table director")
|
||||
XCTAssertNotNil(testController.tableDirector.tableView, "TableDirector should have table view")
|
||||
}
|
||||
|
||||
func testSimpleRowBuilderCreatesRowsAndSection() {
|
||||
|
||||
let source = ["1", "2", "3"]
|
||||
|
||||
let rows = TableRowBuilder<String, UITableViewCell>(items: source)
|
||||
.action(.configure) { data -> Void in
|
||||
|
||||
XCTAssertNotNil(data.cell, "Action should have a cell")
|
||||
data.cell?.textLabel?.text = "\(data.item)"
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
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 += TableConfigurableRowBuilder<TestData, TestTableViewCell>(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 = TableConfigurableRowBuilder<TestData, TestTableViewCell>(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
|
||||
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")
|
||||
|
||||
XCTAssertTrue(testController.tableView.dataSource?.tableView?(testController.tableView, titleForHeaderInSection: 0) == sectionHeaderTitle)
|
||||
XCTAssertTrue(testController.tableView.dataSource?.tableView?(testController.tableView, titleForFooterInSection: 0) == sectionFooterTitle)
|
||||
}
|
||||
|
||||
func testSectionBuilderCreatesSectionWithHeaderAndFooterViews() {
|
||||
|
||||
let row = TableConfigurableRowBuilder<TestData, TestTableViewCell>(items: [TestData(title: "title")])
|
||||
|
||||
let sectionHeaderView = UIView()
|
||||
let sectionFooterView = UIView()
|
||||
|
||||
let section = TableSectionBuilder(headerView: sectionHeaderView, headerHeight: 44, footerView: sectionFooterView, footerHeight: 44)
|
||||
section += row
|
||||
|
||||
testController.view.hidden = false
|
||||
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")
|
||||
|
||||
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 = TableConfigurableRowBuilder<TestData, TestTableViewCell>(items: [TestData(title: "title")])
|
||||
.action(TestTableViewCellOptions.CellAction) { data -> Void 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
|
||||
testController.tableView.reloadData()
|
||||
|
||||
let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as? TestTableViewCell
|
||||
|
||||
XCTAssertNotNil(cell, "Cell should exists and should be TestTableViewCell")
|
||||
|
||||
cell?.raiseAction()
|
||||
|
||||
waitForExpectationsWithTimeout(1.0, handler: nil)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue