diff --git a/.swift-version b/.swift-version index 8012ebb..6e63660 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.2 \ No newline at end of file +5.0 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 228c26b..570d984 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -osx_image: xcode10 +osx_image: xcode11 branches: only: - master @@ -7,17 +7,15 @@ env: global: - LC_CTYPE=en_US.UTF-8 - LANG=en_US.UTF-8 - - IOS_SDK=iphonesimulator12.0 + - IOS_SDK=iphonesimulator13.0 - SCHEME_IOS="TableKit" - PROJECT_FRAMEWORK="TableKit.xcodeproj" matrix: - - 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.3.1,name=iPhone 5" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK" + - DESTINATION="OS=11.1,name=iPhone 6" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK" - DESTINATION="OS=12.0,name=iPhone 7 Plus" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK" + - DESTINATION="OS=13.0,name=iPhone 11" SCHEME="$SCHEME_IOS" SDK="$IOS_SDK" script: - set -o pipefail diff --git a/CHANGELOG.md b/CHANGELOG.md index ebb1a04..3eca5a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. +## [2.10.0](https://github.com/maxsokolov/TableKit/releases/tag/2.10.0) +Released on 2019-09-29. +- Swift 5.1 support. + +## [2.9.0](https://github.com/maxsokolov/TableKit/releases/tag/2.9.0) +Released on 2019-04-04. +- Swift 5.0 support. + ## [2.8.0](https://github.com/maxsokolov/TableKit/releases/tag/2.8.0) Released on 2018-09-30. - Swift 4.2 support. diff --git a/Demo/TableKitDemo.xcodeproj/project.pbxproj b/Demo/TableKitDemo.xcodeproj/project.pbxproj index 17885b9..eef710e 100644 --- a/Demo/TableKitDemo.xcodeproj/project.pbxproj +++ b/Demo/TableKitDemo.xcodeproj/project.pbxproj @@ -248,6 +248,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, Base, ); @@ -377,7 +378,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -425,7 +426,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; VALIDATE_PRODUCT = YES; }; name = Release; @@ -443,7 +444,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.demo; PRODUCT_NAME = TableKitDemo; PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -460,7 +461,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.demo; PRODUCT_NAME = TableKitDemo; PROVISIONING_PROFILE = ""; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Package.swift b/Package.swift index 35ee9ed..5ce7c3d 100644 --- a/Package.swift +++ b/Package.swift @@ -1,5 +1,20 @@ +// swift-tools-version:5.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + import PackageDescription let package = Package( - name: "TableKit" -) \ No newline at end of file + name: "TableKit", + + products: [ + .library( + name: "TableKit", + targets: ["TableKit"]), + ], + + targets: [ + .target( + name: "TableKit", + path: "Sources") + ] +) diff --git a/README.md b/README.md index c13a629..626274c 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@
@@ -204,7 +204,7 @@ tableDirector += rows Done, your table is ready. ## Automatic cell registration -TableKit can register your cells in a table view automatically. In case if your reusable cell id mathces cell's xib name: +TableKit can register your cells in a table view automatically. In case if your reusable cell id matches cell's xib name: ```ruby MyTableViewCell.swift diff --git a/Sources/TableDirector.swift b/Sources/TableDirector.swift index c17ce2c..2ffc99d 100644 --- a/Sources/TableDirector.swift +++ b/Sources/TableDirector.swift @@ -95,6 +95,14 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { tableView?.reloadData() } + // MARK: - Private + private func row(at indexPath: IndexPath) -> Row? { + if indexPath.section < sections.count && indexPath.row < sections[indexPath.section].rows.count { + return sections[indexPath.section].rows[indexPath.row] + } + return nil + } + // MARK: Public @discardableResult open func invoke( @@ -102,15 +110,13 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { cell: UITableViewCell?, indexPath: IndexPath, userInfo: [AnyHashable: Any]? = nil) -> Any? { - if indexPath.section < sections.count && indexPath.row < sections[indexPath.section].rows.count { - return sections[indexPath.section].rows[indexPath.row].invoke( - action: action, - cell: cell, - path: indexPath, - userInfo: userInfo - ) - } - return nil + guard let row = row(at: indexPath) else { return nil } + return row.invoke( + action: action, + cell: cell, + path: indexPath, + userInfo: userInfo + ) } open override func responds(to selector: Selector) -> Bool { @@ -125,7 +131,8 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { // MARK: - Internal func hasAction(_ action: TableRowActionType, atIndexPath indexPath: IndexPath) -> Bool { - return sections[indexPath.section].rows[indexPath.row].has(action: action) + guard let row = row(at: indexPath) else { return false } + return row.has(action: action) } @objc @@ -172,6 +179,8 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { } open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + guard section < sections.count else { return 0 } + return sections[section].numberOfRows } @@ -196,29 +205,39 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { // MARK: UITableViewDataSource - section setup open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + guard section < sections.count else { return nil } + return sections[section].headerTitle } open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { + guard section < sections.count else { return nil } + return sections[section].footerTitle } // MARK: UITableViewDelegate - section setup open func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard section < sections.count else { return nil } + return sections[section].headerView } open func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + guard section < sections.count else { return nil } + return sections[section].footerView } open func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + guard section < sections.count else { return 0 } let section = sections[section] return section.headerHeight ?? section.headerView?.frame.size.height ?? UITableView.automaticDimension } open func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + guard section < sections.count else { return 0 } let section = sections[section] return section.footerHeight @@ -290,6 +309,39 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { return indexPath } + open func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? { + if hasAction(.willDeselect, atIndexPath: indexPath) { + return invoke(action: .willDeselect, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath) as? IndexPath + } + + return indexPath + } + + @available(iOS 13.0, *) + open func tableView( + _ tableView: UITableView, + shouldBeginMultipleSelectionInteractionAt indexPath: IndexPath) -> Bool + { + invoke(action: .shouldBeginMultipleSelection, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath) as? Bool ?? false + } + + @available(iOS 13.0, *) + open func tableView( + _ tableView: UITableView, + didBeginMultipleSelectionInteractionAt indexPath: IndexPath) + { + invoke(action: .didBeginMultipleSelection, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath) + } + + @available(iOS 13.0, *) + open func tableView( + _ tableView: UITableView, + contextMenuConfigurationForRowAt indexPath: IndexPath, + point: CGPoint) -> UIContextMenuConfiguration? + { + invoke(action: .showContextMenu, cell: tableView.cellForRow(at: indexPath), indexPath: indexPath, userInfo: [TableKitUserInfoKeys.ContextMenuInvokePoint: point]) as? UIContextMenuConfiguration + } + // MARK: - Row editing open func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { return sections[indexPath.section].rows[indexPath.row].isEditingAllowed(forIndexPath: indexPath) @@ -328,6 +380,11 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate { open func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { invoke(action: .move, cell: tableView.cellForRow(at: sourceIndexPath), indexPath: sourceIndexPath, userInfo: [TableKitUserInfoKeys.CellMoveDestinationIndexPath: destinationIndexPath]) } + + open func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { + let cell = tableView.cellForRow(at: indexPath) + invoke(action: .accessoryButtonTap, cell: cell, indexPath: indexPath) + } } // MARK: - Sections manipulation diff --git a/Sources/TableKit.swift b/Sources/TableKit.swift index 8206baf..0615871 100644 --- a/Sources/TableKit.swift +++ b/Sources/TableKit.swift @@ -27,6 +27,7 @@ struct TableKitNotifications { public struct TableKitUserInfoKeys { public static let CellMoveDestinationIndexPath = "TableKitCellMoveDestinationIndexPath" public static let CellCanMoveProposedIndexPath = "CellCanMoveProposedIndexPath" + public static let ContextMenuInvokePoint = "ContextMenuInvokePoint" } public protocol RowConfigurable { @@ -71,9 +72,12 @@ public enum TableRowActionType { case select case deselect case willSelect + case willDeselect case willDisplay case didEndDisplaying case shouldHighlight + case shouldBeginMultipleSelection + case didBeginMultipleSelection case height case canEdit case configure @@ -81,6 +85,8 @@ public enum TableRowActionType { case canMove case canMoveTo case move + case showContextMenu + case accessoryButtonTap case custom(String) var key: String { diff --git a/Sources/TableRow.swift b/Sources/TableRow.swift index 8a697fd..662b4dd 100644 --- a/Sources/TableRow.swift +++ b/Sources/TableRow.swift @@ -117,7 +117,7 @@ open class TableRow