commit
81fbd2f5e5
10
.travis.yml
10
.travis.yml
|
|
@ -1,5 +1,5 @@
|
|||
language: objective-c
|
||||
osx_image: xcode7.3
|
||||
osx_image: xcode8
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
|
@ -7,20 +7,20 @@ env:
|
|||
global:
|
||||
- LC_CTYPE=en_US.UTF-8
|
||||
- LANG=en_US.UTF-8
|
||||
- IOS_SDK=iphonesimulator9.3
|
||||
- IOS_SDK=iphonesimulator10.0
|
||||
- SCHEME_IOS="TableKit"
|
||||
- PROJECT_FRAMEWORK="TableKit.xcodeproj"
|
||||
|
||||
matrix:
|
||||
- DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
- DESTINATION="OS=8.2,name=iPhone 5" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
- DESTINATION="OS=9.0,name=iPhone 6" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
- DESTINATION="OS=9.1,name=iPhone 6 Plus" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
- DESTINATION="OS=9.2,name=iPhone 6S" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
- DESTINATION="OS=9.3,name=iPhone 6S Plus" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
- DESTINATION="OS=10.0,name=iPhone 5" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
- DESTINATION="OS=10.0,name=iPhone 7 Plus" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK"
|
||||
|
||||
script:
|
||||
- set -o pipefail
|
||||
- xcodebuild -version
|
||||
- xcodebuild -showsdks
|
||||
- xcodebuild -project "$PROJECT_FRAMEWORK" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO ENABLE_TESTABILITY=YES test | xcpretty -c;
|
||||
- xcodebuild -project "$PROJECT_FRAMEWORK" -scheme "$SCHEME" -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO ENABLE_TESTABILITY=YES test | xcpretty;
|
||||
|
|
@ -25,17 +25,17 @@ class MainController: UIViewController {
|
|||
|
||||
let clickAction = TableRowAction<String, ConfigurableTableViewCell>(.click) { [weak self] (data) in
|
||||
|
||||
switch data.indexPath.row {
|
||||
switch (data.indexPath as NSIndexPath).row {
|
||||
case 0:
|
||||
self?.performSegueWithIdentifier("autolayoutcells", sender: nil)
|
||||
self?.performSegue(withIdentifier: "autolayoutcells", sender: nil)
|
||||
case 1:
|
||||
self?.performSegueWithIdentifier("nibcells", sender: nil)
|
||||
self?.performSegue(withIdentifier: "nibcells", sender: nil)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let rows: [Row] = [
|
||||
let rows = [
|
||||
|
||||
TableRow<String, ConfigurableTableViewCell>(item: "Autolayout cells", actions: [clickAction]),
|
||||
TableRow<String, ConfigurableTableViewCell>(item: "Nib cells", actions: [clickAction])
|
||||
|
|
@ -44,4 +44,4 @@ class MainController: UIViewController {
|
|||
// automatically creates a section, also could be used like tableDirector.append(rows: rows)
|
||||
tableDirector += rows
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,6 @@ class NibCellsController: UITableViewController {
|
|||
|
||||
let rows: [Row] = numbers.map { TableRow<Int, NibTableViewCell>(item: $0, actions: [shouldHighlightAction]) }
|
||||
|
||||
tableDirector.append(rows: rows)
|
||||
_ = tableDirector.append(rows: rows)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class ConfigurableTableViewCell: UITableViewCell, ConfigurableCell {
|
|||
|
||||
func configure(with text: String) {
|
||||
|
||||
accessoryType = .DisclosureIndicator
|
||||
accessoryType = .disclosureIndicator
|
||||
textLabel?.text = text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,12 +227,13 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0720;
|
||||
LastUpgradeCheck = 0700;
|
||||
LastUpgradeCheck = 0800;
|
||||
ORGANIZATIONNAME = Tablet;
|
||||
TargetAttributes = {
|
||||
DAB7EB261BEF787300D2AD5E = {
|
||||
CreatedOnToolsVersion = 7.0.1;
|
||||
DevelopmentTeam = Z48R734SJX;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -330,8 +331,10 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -374,8 +377,10 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -394,6 +399,7 @@
|
|||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
|
|
@ -401,32 +407,34 @@
|
|||
DAB7EB3A1BEF787300D2AD5E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = Resources/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.demo;
|
||||
PRODUCT_NAME = TableKitDemo;
|
||||
PROVISIONING_PROFILE = "";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DAB7EB3B1BEF787300D2AD5E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
|
||||
INFOPLIST_FILE = Resources/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.demo;
|
||||
PRODUCT_NAME = TableKitDemo;
|
||||
PROVISIONING_PROFILE = "";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
<p align="left">
|
||||
<a href="https://travis-ci.org/maxsokolov/TableKit"><img src="https://api.travis-ci.org/maxsokolov/TableKit.svg" alt="Build Status" /></a>
|
||||
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/Swift_2.2-compatible-4BC51D.svg?style=flat" alt="Swift 2.2 compatible" /></a>
|
||||
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/Swift_3.0-compatible-4BC51D.svg?style=flat" alt="Swift 2.2 compatible" /></a>
|
||||
<a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat" alt="Carthage compatible" /></a>
|
||||
<a href="https://cocoapods.org/pods/tablekit"><img src="https://img.shields.io/badge/pod-1.2.0-blue.svg" alt="CocoaPods compatible" /></a>
|
||||
<a href="https://cocoapods.org/pods/tablekit"><img src="https://img.shields.io/badge/pod-1.3.0-blue.svg" alt="CocoaPods compatible" /></a>
|
||||
<img src="https://img.shields.io/badge/platform-iOS-blue.svg?style=flat" alt="Platform iOS" />
|
||||
<a href="https://raw.githubusercontent.com/maxsokolov/tablekit/master/LICENSE"><img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="License: MIT" /></a>
|
||||
</p>
|
||||
|
|
@ -177,7 +177,7 @@ let click = TableRowAction<String, UserTableViewCell>(.click) {
|
|||
|
||||
}
|
||||
|
||||
let rows: [Row] = users.filter({ $0.state == .active }).map({ TableRow<String, UserTableViewCell>(item: $0.name, actions: [click]) })
|
||||
let rows = users.filter({ $0.state == .active }).map({ TableRow<String, UserTableViewCell>(item: $0.name, actions: [click]) })
|
||||
|
||||
tableDirector += rows
|
||||
```
|
||||
|
|
@ -212,8 +212,8 @@ Clone the repo and drag files from `Sources` folder into your Xcode project.
|
|||
|
||||
# Requirements
|
||||
|
||||
- iOS 8.0+
|
||||
- Xcode 7.0+
|
||||
- iOS 8.0
|
||||
- Xcode 8.0
|
||||
|
||||
# License
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public extension ConfigurableCell where Self: UITableViewCell {
|
|||
|
||||
static var reuseIdentifier: String {
|
||||
get {
|
||||
return String(self)
|
||||
return String(describing: self)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -52,4 +52,4 @@ public extension ConfigurableCell where Self: UITableViewCell {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,24 +22,24 @@ import UIKit
|
|||
|
||||
public protocol CellHeightCalculatable {
|
||||
|
||||
func height(row: Row, path: NSIndexPath) -> CGFloat
|
||||
func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat
|
||||
func height(_ row: Row, path: IndexPath) -> CGFloat
|
||||
func estimatedHeight(_ row: Row, path: IndexPath) -> CGFloat
|
||||
|
||||
func invalidate()
|
||||
}
|
||||
|
||||
public class PrototypeHeightStrategy: CellHeightCalculatable {
|
||||
open class PrototypeHeightStrategy: CellHeightCalculatable {
|
||||
|
||||
private weak var tableView: UITableView?
|
||||
private var prototypes = [String: UITableViewCell]()
|
||||
private var cachedHeights = [Int: CGFloat]()
|
||||
private var separatorHeight = 1 / UIScreen.mainScreen().scale
|
||||
private var separatorHeight = 1 / UIScreen.main.scale
|
||||
|
||||
init(tableView: UITableView?) {
|
||||
self.tableView = tableView
|
||||
}
|
||||
|
||||
public func height(row: Row, path: NSIndexPath) -> CGFloat {
|
||||
open func height(_ row: Row, path: IndexPath) -> CGFloat {
|
||||
|
||||
guard let tableView = tableView else { return 0 }
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
|
|||
var prototypeCell = prototypes[row.reuseIdentifier]
|
||||
if prototypeCell == nil {
|
||||
|
||||
prototypeCell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier)
|
||||
prototypeCell = tableView.dequeueReusableCell(withIdentifier: row.reuseIdentifier)
|
||||
prototypes[row.reuseIdentifier] = prototypeCell
|
||||
}
|
||||
|
||||
|
|
@ -60,18 +60,18 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
|
|||
|
||||
row.configure(cell)
|
||||
|
||||
cell.bounds = CGRectMake(0, 0, tableView.bounds.size.width, cell.bounds.height)
|
||||
cell.bounds = CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: cell.bounds.height)
|
||||
cell.setNeedsLayout()
|
||||
cell.layoutIfNeeded()
|
||||
|
||||
let height = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + (tableView.separatorStyle != .None ? separatorHeight : 0)
|
||||
let height = cell.contentView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height + (tableView.separatorStyle != .none ? separatorHeight : 0)
|
||||
|
||||
cachedHeights[hash] = height
|
||||
|
||||
return height
|
||||
}
|
||||
|
||||
public func estimatedHeight(row: Row, path: NSIndexPath) -> CGFloat {
|
||||
open func estimatedHeight(_ row: Row, path: IndexPath) -> CGFloat {
|
||||
|
||||
guard let tableView = tableView else { return 0 }
|
||||
|
||||
|
|
@ -81,14 +81,14 @@ public class PrototypeHeightStrategy: CellHeightCalculatable {
|
|||
return height
|
||||
}
|
||||
|
||||
if let estimatedHeight = row.estimatedHeight where estimatedHeight > 0 {
|
||||
if let estimatedHeight = row.estimatedHeight , estimatedHeight > 0 {
|
||||
return estimatedHeight
|
||||
}
|
||||
|
||||
return UITableViewAutomaticDimension
|
||||
}
|
||||
|
||||
public func invalidate() {
|
||||
open func invalidate() {
|
||||
cachedHeights.removeAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,27 +20,27 @@
|
|||
|
||||
// --
|
||||
public func +=(left: TableDirector, right: TableSection) {
|
||||
left.append(section: right)
|
||||
_ = left.append(section: right)
|
||||
}
|
||||
|
||||
public func +=(left: TableDirector, right: [TableSection]) {
|
||||
left.append(sections: right)
|
||||
_ = left.append(sections: right)
|
||||
}
|
||||
|
||||
// --
|
||||
public func +=(left: TableDirector, right: Row) {
|
||||
left.append(sections: [TableSection(rows: [right])])
|
||||
_ = left.append(sections: [TableSection(rows: [right])])
|
||||
}
|
||||
|
||||
public func +=(left: TableDirector, right: [Row]) {
|
||||
left.append(sections: [TableSection(rows: right)])
|
||||
_ = left.append(sections: [TableSection(rows: right)])
|
||||
}
|
||||
|
||||
// --
|
||||
public func +=(left: TableSection, right: Row) {
|
||||
left.append(row: right)
|
||||
_ = left.append(row: right)
|
||||
}
|
||||
|
||||
public func +=(left: TableSection, right: [Row]) {
|
||||
left.append(rows: right)
|
||||
}
|
||||
_ = left.append(rows: right)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,25 +28,25 @@ struct TableKitNotifications {
|
|||
A custom action that you can trigger from your cell.
|
||||
You can easily catch actions using a chaining manner with your row.
|
||||
*/
|
||||
public class TableCellAction {
|
||||
open class TableCellAction {
|
||||
|
||||
/// The cell that triggers an action.
|
||||
public let cell: UITableViewCell
|
||||
open let cell: UITableViewCell
|
||||
|
||||
/// The action unique key.
|
||||
public let key: String
|
||||
open let key: String
|
||||
|
||||
/// The custom user info.
|
||||
public let userInfo: [NSObject: AnyObject]?
|
||||
open let userInfo: [AnyHashable: Any]?
|
||||
|
||||
public init(key: String, sender: UITableViewCell, userInfo: [NSObject: AnyObject]? = nil) {
|
||||
public init(key: String, sender: UITableViewCell, userInfo: [AnyHashable: Any]? = nil) {
|
||||
|
||||
self.key = key
|
||||
self.cell = sender
|
||||
self.userInfo = userInfo
|
||||
}
|
||||
|
||||
public func invoke() {
|
||||
NSNotificationCenter.defaultCenter().postNotificationName(TableKitNotifications.CellAction, object: self, userInfo: userInfo)
|
||||
open func invoke() {
|
||||
NotificationCenter.default.post(name: Notification.Name(rawValue: TableKitNotifications.CellAction), object: self, userInfo: userInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,30 +29,30 @@ class TableCellRegisterer {
|
|||
self.tableView = tableView
|
||||
}
|
||||
|
||||
func register(cellType cellType: AnyClass, forCellReuseIdentifier reuseIdentifier: String) {
|
||||
func register(cellType: AnyClass, forCellReuseIdentifier reuseIdentifier: String) {
|
||||
|
||||
if registeredIds.contains(reuseIdentifier) {
|
||||
return
|
||||
}
|
||||
|
||||
// check if cell is already registered, probably cell has been registered by storyboard
|
||||
if tableView?.dequeueReusableCellWithIdentifier(reuseIdentifier) != nil {
|
||||
if tableView?.dequeueReusableCell(withIdentifier: reuseIdentifier) != nil {
|
||||
|
||||
registeredIds.insert(reuseIdentifier)
|
||||
return
|
||||
}
|
||||
|
||||
let bundle = NSBundle(forClass: cellType)
|
||||
let bundle = Bundle(for: cellType)
|
||||
|
||||
// we hope that cell's xib file has name that equals to cell's class name
|
||||
// in that case we could register nib
|
||||
if let _ = bundle.pathForResource(reuseIdentifier, ofType: "nib") {
|
||||
tableView?.registerNib(UINib(nibName: reuseIdentifier, bundle: bundle), forCellReuseIdentifier: reuseIdentifier)
|
||||
if let _ = bundle.path(forResource: reuseIdentifier, ofType: "nib") {
|
||||
tableView?.register(UINib(nibName: reuseIdentifier, bundle: bundle), forCellReuseIdentifier: reuseIdentifier)
|
||||
// otherwise, register cell class
|
||||
} else {
|
||||
tableView?.registerClass(cellType, forCellReuseIdentifier: reuseIdentifier)
|
||||
tableView?.register(cellType, forCellReuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
registeredIds.insert(reuseIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,16 +23,16 @@ import UIKit
|
|||
/**
|
||||
Responsible for table view's datasource and delegate.
|
||||
*/
|
||||
public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
|
||||
open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
|
||||
|
||||
public private(set) weak var tableView: UITableView?
|
||||
public private(set) var sections = [TableSection]()
|
||||
open private(set) weak var tableView: UITableView?
|
||||
open private(set) var sections = [TableSection]()
|
||||
|
||||
private weak var scrollDelegate: UIScrollViewDelegate?
|
||||
private var heightStrategy: CellHeightCalculatable?
|
||||
private var cellRegisterer: TableCellRegisterer?
|
||||
|
||||
public var shouldUsePrototypeCellHeightCalculation: Bool = false {
|
||||
open var shouldUsePrototypeCellHeightCalculation: Bool = false {
|
||||
didSet {
|
||||
if shouldUsePrototypeCellHeightCalculation {
|
||||
heightStrategy = PrototypeHeightStrategy(tableView: tableView)
|
||||
|
|
@ -40,7 +40,7 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
}
|
||||
}
|
||||
|
||||
public var isEmpty: Bool {
|
||||
open var isEmpty: Bool {
|
||||
return sections.isEmpty
|
||||
}
|
||||
|
||||
|
|
@ -56,57 +56,57 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
self.tableView?.delegate = self
|
||||
self.tableView?.dataSource = self
|
||||
|
||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(didReceiveAction), name: TableKitNotifications.CellAction, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(didReceiveAction), name: NSNotification.Name(rawValue: TableKitNotifications.CellAction), object: nil)
|
||||
}
|
||||
|
||||
deinit {
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
public func reload() {
|
||||
open func reload() {
|
||||
tableView?.reloadData()
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
public func invoke(action action: TableRowActionType, cell: UITableViewCell?, indexPath: NSIndexPath) -> Any? {
|
||||
return sections[indexPath.section].rows[indexPath.row].invoke(action, cell: cell, path: indexPath)
|
||||
open func invoke(action: TableRowActionType, cell: UITableViewCell?, indexPath: IndexPath) -> Any? {
|
||||
return sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row].invoke(action, cell: cell, path: indexPath)
|
||||
}
|
||||
|
||||
public override func respondsToSelector(selector: Selector) -> Bool {
|
||||
return super.respondsToSelector(selector) || scrollDelegate?.respondsToSelector(selector) == true
|
||||
open override func responds(to selector: Selector) -> Bool {
|
||||
return super.responds(to: selector) || scrollDelegate?.responds(to: selector) == true
|
||||
}
|
||||
|
||||
public override func forwardingTargetForSelector(selector: Selector) -> AnyObject? {
|
||||
return scrollDelegate?.respondsToSelector(selector) == true ? scrollDelegate : super.forwardingTargetForSelector(selector)
|
||||
open override func forwardingTarget(for selector: Selector) -> Any? {
|
||||
return scrollDelegate?.responds(to: selector) == true ? scrollDelegate : super.forwardingTarget(for: selector)
|
||||
}
|
||||
|
||||
// MARK: - Internal -
|
||||
|
||||
func hasAction(action: TableRowActionType, atIndexPath indexPath: NSIndexPath) -> Bool {
|
||||
return sections[indexPath.section].rows[indexPath.row].hasAction(action)
|
||||
func hasAction(_ action: TableRowActionType, atIndexPath indexPath: IndexPath) -> Bool {
|
||||
return sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row].hasAction(action)
|
||||
}
|
||||
|
||||
func didReceiveAction(notification: NSNotification) {
|
||||
func didReceiveAction(_ notification: Notification) {
|
||||
|
||||
guard let action = notification.object as? TableCellAction, indexPath = tableView?.indexPathForCell(action.cell) else { return }
|
||||
invoke(action: .custom(action.key), cell: action.cell, indexPath: indexPath)
|
||||
guard let action = notification.object as? TableCellAction, let indexPath = tableView?.indexPath(for: action.cell) else { return }
|
||||
_ = invoke(action: .custom(action.key), cell: action.cell, indexPath: indexPath)
|
||||
}
|
||||
|
||||
// MARK: - Height
|
||||
|
||||
public func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
|
||||
let row = sections[indexPath.section].rows[indexPath.row]
|
||||
let row = sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row]
|
||||
|
||||
cellRegisterer?.register(cellType: row.cellType, forCellReuseIdentifier: row.reuseIdentifier)
|
||||
|
||||
return row.estimatedHeight ?? heightStrategy?.estimatedHeight(row, path: indexPath) ?? UITableViewAutomaticDimension
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
|
||||
open func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
|
||||
let row = sections[indexPath.section].rows[indexPath.row]
|
||||
let row = sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row]
|
||||
|
||||
let rowHeight = invoke(action: .height, cell: nil, indexPath: indexPath) as? CGFloat
|
||||
|
||||
|
|
@ -115,57 +115,57 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
|
||||
// MARK: UITableViewDataSource - configuration
|
||||
|
||||
public func numberOfSectionsInTableView(tableView: UITableView) -> Int {
|
||||
open func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return sections.count
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return sections[section].numberOfRows
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||
open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
||||
let row = sections[indexPath.section].rows[indexPath.row]
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier(row.reuseIdentifier, forIndexPath: indexPath)
|
||||
let row = sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row]
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: row.reuseIdentifier, for: indexPath)
|
||||
|
||||
if cell.frame.size.width != tableView.frame.size.width {
|
||||
cell.frame = CGRectMake(0, 0, tableView.frame.size.width, cell.frame.size.height)
|
||||
cell.frame = CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: cell.frame.size.height)
|
||||
cell.layoutIfNeeded()
|
||||
}
|
||||
|
||||
row.configure(cell)
|
||||
invoke(action: .configure, cell: cell, indexPath: indexPath)
|
||||
_ = invoke(action: .configure, cell: cell, indexPath: indexPath)
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
// MARK: UITableViewDataSource - section setup
|
||||
|
||||
public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return sections[section].headerTitle
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
return sections[section].footerTitle
|
||||
}
|
||||
|
||||
// MARK: UITableViewDelegate - section setup
|
||||
|
||||
public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||
open func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
|
||||
return sections[section].headerView
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
||||
open func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
||||
return sections[section].footerView
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
open func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
|
||||
let section = sections[section]
|
||||
return section.headerHeight ?? section.headerView?.frame.size.height ?? 0
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
|
||||
open func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
|
||||
|
||||
let section = sections[section]
|
||||
return section.footerHeight ?? section.footerView?.frame.size.height ?? 0
|
||||
|
|
@ -173,89 +173,89 @@ public class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate
|
|||
|
||||
// MARK: UITableViewDelegate - actions
|
||||
|
||||
public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
|
||||
open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
|
||||
let cell = tableView.cellForRowAtIndexPath(indexPath)
|
||||
let cell = tableView.cellForRow(at: indexPath)
|
||||
|
||||
if invoke(action: .click, cell: cell, indexPath: indexPath) != nil {
|
||||
tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
} else {
|
||||
invoke(action: .select, cell: cell, indexPath: indexPath)
|
||||
_ = invoke(action: .select, cell: cell, indexPath: indexPath)
|
||||
}
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
|
||||
invoke(action: .deselect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath)
|
||||
open func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
|
||||
_ = invoke(action: .deselect, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath)
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
|
||||
invoke(action: .willDisplay, cell: cell, indexPath: indexPath)
|
||||
open func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
|
||||
_ = invoke(action: .willDisplay, cell: cell, indexPath: indexPath)
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
|
||||
return invoke(action: .shouldHighlight, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? Bool ?? true
|
||||
open func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
|
||||
return invoke(action: .shouldHighlight, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath) as? Bool ?? true
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
|
||||
open func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
|
||||
|
||||
if hasAction(.willSelect, atIndexPath: indexPath) {
|
||||
return invoke(action: .willSelect, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath) as? NSIndexPath
|
||||
return invoke(action: .willSelect, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath) as? IndexPath
|
||||
}
|
||||
return indexPath
|
||||
}
|
||||
|
||||
// MARK: - Row editing -
|
||||
|
||||
public func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
|
||||
return sections[indexPath.section].rows[indexPath.row].isEditingAllowed(forIndexPath: indexPath)
|
||||
open func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||
return sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row].isEditingAllowed(forIndexPath: indexPath)
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
|
||||
return sections[indexPath.section].rows[indexPath.row].editingActions
|
||||
open func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||
return sections[(indexPath as NSIndexPath).section].rows[(indexPath as NSIndexPath).row].editingActions
|
||||
}
|
||||
|
||||
public func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
|
||||
open func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
|
||||
|
||||
if editingStyle == .Delete {
|
||||
invoke(action: .clickDelete, cell: tableView.cellForRowAtIndexPath(indexPath), indexPath: indexPath)
|
||||
if editingStyle == .delete {
|
||||
_ = invoke(action: .clickDelete, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Sections manipulation -
|
||||
|
||||
public func append(section section: TableSection) -> Self {
|
||||
open func append(section: TableSection) -> Self {
|
||||
|
||||
append(sections: [section])
|
||||
_ = append(sections: [section])
|
||||
return self
|
||||
}
|
||||
|
||||
public func append(sections sections: [TableSection]) -> Self {
|
||||
open func append(sections: [TableSection]) -> Self {
|
||||
|
||||
self.sections.appendContentsOf(sections)
|
||||
self.sections.append(contentsOf: sections)
|
||||
return self
|
||||
}
|
||||
|
||||
public func append(rows rows: [Row]) -> Self {
|
||||
open func append(rows: [Row]) -> Self {
|
||||
|
||||
append(section: TableSection(rows: rows))
|
||||
_ = append(section: TableSection(rows: rows))
|
||||
return self
|
||||
}
|
||||
|
||||
public func insert(section section: TableSection, atIndex index: Int) -> Self {
|
||||
open func insert(section: TableSection, atIndex index: Int) -> Self {
|
||||
|
||||
sections.insert(section, atIndex: index)
|
||||
sections.insert(section, at: index)
|
||||
return self
|
||||
}
|
||||
|
||||
public func delete(index index: Int) -> Self {
|
||||
open func delete(index: Int) -> Self {
|
||||
|
||||
sections.removeAtIndex(index)
|
||||
sections.remove(at: index)
|
||||
return self
|
||||
}
|
||||
|
||||
public func clear() -> Self {
|
||||
open func clear() -> Self {
|
||||
|
||||
sections.removeAll()
|
||||
return self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,16 +22,16 @@ import UIKit
|
|||
|
||||
public protocol RowConfigurable {
|
||||
|
||||
func configure(cell: UITableViewCell)
|
||||
func configure(_ cell: UITableViewCell)
|
||||
}
|
||||
|
||||
public protocol RowActionable {
|
||||
|
||||
var editingActions: [UITableViewRowAction]? { get }
|
||||
func isEditingAllowed(forIndexPath indexPath: NSIndexPath) -> Bool
|
||||
func isEditingAllowed(forIndexPath indexPath: IndexPath) -> Bool
|
||||
|
||||
func invoke(action: TableRowActionType, cell: UITableViewCell?, path: NSIndexPath) -> Any?
|
||||
func hasAction(action: TableRowActionType) -> Bool
|
||||
func invoke(_ action: TableRowActionType, cell: UITableViewCell?, path: IndexPath) -> Any?
|
||||
func hasAction(_ action: TableRowActionType) -> Bool
|
||||
}
|
||||
|
||||
public protocol RowHashable {
|
||||
|
|
@ -48,29 +48,29 @@ public protocol Row: RowConfigurable, RowActionable, RowHashable {
|
|||
var defaultHeight: CGFloat? { get }
|
||||
}
|
||||
|
||||
public class TableRow<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell>: Row {
|
||||
open class TableRow<ItemType, CellType: ConfigurableCell>: Row where CellType.T == ItemType, CellType: UITableViewCell {
|
||||
|
||||
public let item: ItemType
|
||||
open let item: ItemType
|
||||
private lazy var actions = [String: TableRowAction<ItemType, CellType>]()
|
||||
private(set) public var editingActions: [UITableViewRowAction]?
|
||||
private(set) open var editingActions: [UITableViewRowAction]?
|
||||
|
||||
public var hashValue: Int {
|
||||
open var hashValue: Int {
|
||||
return ObjectIdentifier(self).hashValue
|
||||
}
|
||||
|
||||
public var reuseIdentifier: String {
|
||||
open var reuseIdentifier: String {
|
||||
return CellType.reuseIdentifier
|
||||
}
|
||||
|
||||
public var estimatedHeight: CGFloat? {
|
||||
open var estimatedHeight: CGFloat? {
|
||||
return CellType.estimatedHeight
|
||||
}
|
||||
|
||||
public var defaultHeight: CGFloat? {
|
||||
open var defaultHeight: CGFloat? {
|
||||
return CellType.defaultHeight
|
||||
}
|
||||
|
||||
public var cellType: AnyClass {
|
||||
open var cellType: AnyClass {
|
||||
return CellType.self
|
||||
}
|
||||
|
||||
|
|
@ -83,21 +83,21 @@ public class TableRow<ItemType, CellType: ConfigurableCell where CellType.T == I
|
|||
|
||||
// MARK: - RowConfigurable -
|
||||
|
||||
public func configure(cell: UITableViewCell) {
|
||||
open func configure(_ cell: UITableViewCell) {
|
||||
(cell as? CellType)?.configure(with: item)
|
||||
}
|
||||
|
||||
// MARK: - RowActionable -
|
||||
|
||||
public func invoke(action: TableRowActionType, cell: UITableViewCell?, path: NSIndexPath) -> Any? {
|
||||
open func invoke(_ action: TableRowActionType, cell: UITableViewCell?, path: IndexPath) -> Any? {
|
||||
return actions[action.key]?.invoke(item: item, cell: cell, path: path)
|
||||
}
|
||||
|
||||
public func hasAction(action: TableRowActionType) -> Bool {
|
||||
open func hasAction(_ action: TableRowActionType) -> Bool {
|
||||
return actions[action.key] != nil
|
||||
}
|
||||
|
||||
public func isEditingAllowed(forIndexPath indexPath: NSIndexPath) -> Bool {
|
||||
open func isEditingAllowed(forIndexPath indexPath: IndexPath) -> Bool {
|
||||
|
||||
if actions[TableRowActionType.canEdit.key] != nil {
|
||||
return invoke(.canEdit, cell: nil, path: indexPath) as? Bool ?? false
|
||||
|
|
@ -107,15 +107,15 @@ public class TableRow<ItemType, CellType: ConfigurableCell where CellType.T == I
|
|||
|
||||
// MARK: - actions -
|
||||
|
||||
public func action(action: TableRowAction<ItemType, CellType>) -> Self {
|
||||
open func action(_ action: TableRowAction<ItemType, CellType>) -> Self {
|
||||
|
||||
actions[action.type.key] = action
|
||||
return self
|
||||
}
|
||||
|
||||
public func action<T>(type: TableRowActionType, handler: (data: TableRowActionData<ItemType, CellType>) -> T) -> Self {
|
||||
open func action<T>(_ type: TableRowActionType, handler: @escaping (_ data: TableRowActionData<ItemType, CellType>) -> T) -> Self {
|
||||
|
||||
actions[type.key] = TableRowAction(type, handler: handler)
|
||||
actions[type.key] = TableRowAction<ItemType, CellType>(type, handler: handler)
|
||||
return self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,14 +45,14 @@ public enum TableRowActionType {
|
|||
}
|
||||
}
|
||||
|
||||
public class TableRowActionData<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell> {
|
||||
open class TableRowActionData<ItemType, CellType: ConfigurableCell> where CellType.T == ItemType, CellType: UITableViewCell {
|
||||
|
||||
public let item: ItemType
|
||||
public let cell: CellType?
|
||||
public let indexPath: NSIndexPath
|
||||
public let userInfo: [NSObject: AnyObject]?
|
||||
open let item: ItemType
|
||||
open let cell: CellType?
|
||||
open let indexPath: IndexPath
|
||||
open let userInfo: [AnyHashable: Any]?
|
||||
|
||||
init(item: ItemType, cell: CellType?, path: NSIndexPath, userInfo: [NSObject: AnyObject]?) {
|
||||
init(item: ItemType, cell: CellType?, path: IndexPath, userInfo: [AnyHashable: Any]?) {
|
||||
|
||||
self.item = item
|
||||
self.cell = cell
|
||||
|
|
@ -61,24 +61,40 @@ public class TableRowActionData<ItemType, CellType: ConfigurableCell where CellT
|
|||
}
|
||||
}
|
||||
|
||||
public class TableRowAction<ItemType, CellType: ConfigurableCell where CellType.T == ItemType, CellType: UITableViewCell> {
|
||||
private enum TableRowActionHandler<ItemType, CellType: ConfigurableCell> where CellType.T == ItemType, CellType: UITableViewCell {
|
||||
|
||||
public let type: TableRowActionType
|
||||
private let handler: ((data: TableRowActionData<ItemType, CellType>) -> Any?)
|
||||
case voidAction((TableRowActionData<ItemType, CellType>) -> Void)
|
||||
case action((TableRowActionData<ItemType, CellType>) -> Any?)
|
||||
|
||||
public init(_ type: TableRowActionType, handler: (data: TableRowActionData<ItemType, CellType>) -> Void) {
|
||||
func invoke(item: ItemType, cell: UITableViewCell?, path: IndexPath) -> Any? {
|
||||
|
||||
switch self {
|
||||
case .voidAction(let handler):
|
||||
return handler(TableRowActionData(item: item, cell: cell as? CellType, path: path, userInfo: nil))
|
||||
case .action(let handler):
|
||||
return handler(TableRowActionData(item: item, cell: cell as? CellType, path: path, userInfo: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class TableRowAction<ItemType, CellType: ConfigurableCell> where CellType.T == ItemType, CellType: UITableViewCell {
|
||||
|
||||
open let type: TableRowActionType
|
||||
private let handler: TableRowActionHandler<ItemType, CellType>
|
||||
|
||||
public init(_ type: TableRowActionType, handler: @escaping (_ data: TableRowActionData<ItemType, CellType>) -> Void) {
|
||||
|
||||
self.type = type
|
||||
self.handler = handler
|
||||
self.handler = .voidAction(handler)
|
||||
}
|
||||
|
||||
public init<T>(_ type: TableRowActionType, handler: (data: TableRowActionData<ItemType, CellType>) -> T) {
|
||||
public init<T>(_ type: TableRowActionType, handler: @escaping (_ data: TableRowActionData<ItemType, CellType>) -> T) {
|
||||
|
||||
self.type = type
|
||||
self.handler = handler
|
||||
self.handler = .action(handler)
|
||||
}
|
||||
|
||||
func invoke(item item: ItemType, cell: UITableViewCell?, path: NSIndexPath) -> Any? {
|
||||
return handler(data: TableRowActionData(item: item, cell: cell as? CellType, path: path, userInfo: nil))
|
||||
func invoke(item: ItemType, cell: UITableViewCell?, path: IndexPath) -> Any? {
|
||||
return handler.invoke(item: item, cell: cell, path: path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,31 +20,31 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
public class TableSection {
|
||||
open class TableSection {
|
||||
|
||||
public private(set) var rows = [Row]()
|
||||
open private(set) var rows = [Row]()
|
||||
|
||||
public var headerTitle: String?
|
||||
public var footerTitle: String?
|
||||
open var headerTitle: String?
|
||||
open var footerTitle: String?
|
||||
|
||||
public var headerView: UIView?
|
||||
public var footerView: UIView?
|
||||
open var headerView: UIView?
|
||||
open var footerView: UIView?
|
||||
|
||||
public var headerHeight: CGFloat? = nil
|
||||
public var footerHeight: CGFloat? = nil
|
||||
open var headerHeight: CGFloat? = nil
|
||||
open var footerHeight: CGFloat? = nil
|
||||
|
||||
public var numberOfRows: Int {
|
||||
open var numberOfRows: Int {
|
||||
return rows.count
|
||||
}
|
||||
|
||||
public var isEmpty: Bool {
|
||||
open var isEmpty: Bool {
|
||||
return rows.isEmpty
|
||||
}
|
||||
|
||||
public init(rows: [Row]? = nil) {
|
||||
|
||||
if let initialRows = rows {
|
||||
self.rows.appendContentsOf(initialRows)
|
||||
self.rows.append(contentsOf: initialRows)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -64,31 +64,31 @@ public class TableSection {
|
|||
|
||||
// MARK: - Public -
|
||||
|
||||
public func clear() {
|
||||
open func clear() {
|
||||
rows.removeAll()
|
||||
}
|
||||
|
||||
public func append(row row: Row) {
|
||||
open func append(row: Row) {
|
||||
append(rows: [row])
|
||||
}
|
||||
|
||||
public func append(rows rows: [Row]) {
|
||||
self.rows.appendContentsOf(rows)
|
||||
open func append(rows: [Row]) {
|
||||
self.rows.append(contentsOf: rows)
|
||||
}
|
||||
|
||||
public func insert(row row: Row, at index: Int) {
|
||||
rows.insert(row, atIndex: index)
|
||||
open func insert(row: Row, at index: Int) {
|
||||
rows.insert(row, at: index)
|
||||
}
|
||||
|
||||
public func insert(rows rows: [Row], at index: Int) {
|
||||
self.rows.insertContentsOf(rows, at: index)
|
||||
open func insert(rows: [Row], at index: Int) {
|
||||
self.rows.insert(contentsOf: rows, at: index)
|
||||
}
|
||||
|
||||
public func replace(rowAt index: Int, with row: Row) {
|
||||
open func replace(rowAt index: Int, with row: Row) {
|
||||
rows[index] = row
|
||||
}
|
||||
|
||||
public func delete(index index: Int) {
|
||||
rows.removeAtIndex(index)
|
||||
open func delete(index: Int) {
|
||||
rows.remove(at: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@ Pod::Spec.new do |s|
|
|||
s.name = 'TableKit'
|
||||
s.module_name = 'TableKit'
|
||||
|
||||
s.version = '1.2.0'
|
||||
s.version = '1.3.0'
|
||||
|
||||
s.homepage = 'https://github.com/maxsokolov/TableKit'
|
||||
s.summary = 'Type-safe declarative table views. Swift 2.2 is required.'
|
||||
s.summary = 'Type-safe declarative table views with Swift.'
|
||||
|
||||
s.author = { 'Max Sokolov' => 'i@maxsokolov.net' }
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -174,14 +174,16 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0730;
|
||||
LastUpgradeCheck = 0800;
|
||||
ORGANIZATIONNAME = "Max Sokolov";
|
||||
TargetAttributes = {
|
||||
DA9EA7551D0B679A0021F650 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
DA9EA7C31D0EC45F0021F650 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -270,8 +272,10 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -319,8 +323,10 @@
|
|||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
|
|
@ -340,6 +346,7 @@
|
|||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
|
@ -351,6 +358,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
|
@ -363,6 +371,7 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -370,6 +379,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
DEFINES_MODULE = YES;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
|
|
@ -381,6 +391,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
@ -392,6 +403,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -403,6 +415,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0730"
|
||||
LastUpgradeVersion = "0800"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class TabletTests: XCTestCase {
|
|||
super.setUp()
|
||||
|
||||
testController = TestController()
|
||||
testController.view.hidden = false
|
||||
testController.view.isHidden = false
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
|
|
@ -99,10 +99,10 @@ class TabletTests: XCTestCase {
|
|||
testController.tableDirector += row
|
||||
testController.tableView.reloadData()
|
||||
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSections?(in: testController.tableView) == 1, "Table view should have a section")
|
||||
XCTAssertTrue(testController.tableView.dataSource?.tableView(testController.tableView, numberOfRowsInSection: 0) == 1, "Table view should have certain number of rows in a section")
|
||||
|
||||
let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as? TestTableViewCell
|
||||
let cell = testController.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? TestTableViewCell
|
||||
XCTAssertNotNil(cell)
|
||||
XCTAssertTrue(cell?.textLabel?.text == data.title)
|
||||
}
|
||||
|
|
@ -116,12 +116,12 @@ class TabletTests: XCTestCase {
|
|||
testController.tableDirector += rows
|
||||
testController.tableView.reloadData()
|
||||
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSections?(in: testController.tableView) == 1, "Table view should have a section")
|
||||
XCTAssertTrue(testController.tableView.dataSource?.tableView(testController.tableView, numberOfRowsInSection: 0) == data.count, "Table view should have certain number of rows in a section")
|
||||
|
||||
for (index, element) in data.enumerate() {
|
||||
for (index, element) in data.enumerated() {
|
||||
|
||||
let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0)) as? TestTableViewCell
|
||||
let cell = testController.tableView.cellForRow(at: IndexPath(row: index, section: 0)) as? TestTableViewCell
|
||||
XCTAssertNotNil(cell)
|
||||
XCTAssertTrue(cell?.textLabel?.text == element.title)
|
||||
}
|
||||
|
|
@ -139,7 +139,7 @@ class TabletTests: XCTestCase {
|
|||
testController.tableDirector += section
|
||||
testController.tableView.reloadData()
|
||||
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSections?(in: 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)
|
||||
|
|
@ -159,7 +159,7 @@ class TabletTests: XCTestCase {
|
|||
testController.tableDirector += section
|
||||
testController.tableView.reloadData()
|
||||
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSectionsInTableView?(testController.tableView) == 1, "Table view should have a section")
|
||||
XCTAssertTrue(testController.tableView.dataSource?.numberOfSections?(in: 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)
|
||||
|
|
@ -168,7 +168,7 @@ class TabletTests: XCTestCase {
|
|||
|
||||
func testRowBuilderCustomActionInvokedAndSentUserInfo() {
|
||||
|
||||
let expectation = expectationWithDescription("cell action")
|
||||
let expectation = self.expectation(description: "cell action")
|
||||
|
||||
let row = TableRow<TestData, TestTableViewCell>(item: TestData(title: "title"))
|
||||
.action(TableRowAction(.custom(TestTableViewCellOptions.CellAction)) { (data) in
|
||||
|
|
@ -178,16 +178,16 @@ class TabletTests: XCTestCase {
|
|||
expectation.fulfill()
|
||||
})
|
||||
|
||||
testController.view.hidden = false
|
||||
testController.view.isHidden = false
|
||||
testController.tableDirector += row
|
||||
testController.tableView.reloadData()
|
||||
|
||||
let cell = testController.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0)) as? TestTableViewCell
|
||||
let cell = testController.tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? TestTableViewCell
|
||||
|
||||
XCTAssertNotNil(cell, "Cell should exists and should be TestTableViewCell")
|
||||
|
||||
cell?.raiseAction()
|
||||
|
||||
waitForExpectationsWithTimeout(1.0, handler: nil)
|
||||
waitForExpectations(timeout: 1.0, handler: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue