Compare commits

..

41 Commits

Author SHA1 Message Date
Ivan Smolin fec9537745 up swift version to 5.7 2024-01-30 23:09:39 +03:00
Ivan Smolin 246c0d06c0 Merge pull request 'remove outdated actions and swift tools version' (#2) from feature/remote_outdated_code into master
Reviewed-on: #2
2024-01-30 22:27:14 +03:00
Ivan Smolin 54bf141aff remove outdated actions and swift tools version 2024-01-30 22:24:27 +03:00
Ivan Smolin 01134b83b4 update source url 2024-01-30 22:13:02 +03:00
Ivan Smolin 3fefa09c3a Merge pull request 'fix warnings' (#1) from fix/xcode_15 into master
Reviewed-on: #1
2024-01-30 22:08:00 +03:00
Ivan Smolin 4886e43d20 fix warnings 2024-01-30 22:01:31 +03:00
Loupehope 41826e18db
Merge pull request #6 from TouchInstinct/feature/actionRows
Replace UITableViewRowAction with UIContextualAction
2020-12-26 15:37:30 +03:00
Vlad caec2dd10e Return deprecated 2020-12-26 15:22:00 +03:00
Vlad efc03d7c22 Add performsFirstActionWithFullSwipe 2020-12-26 11:24:59 +03:00
Vlad 94c40faa63 Code correction 2020-12-26 11:05:20 +03:00
Vlad d87a23587e Add backward capability to editingActions 2020-12-26 10:52:06 +03:00
Vlad 49b3f868f3 Return IPHONEOS_DEPLOYMENT_TARGET 2020-12-26 10:36:32 +03:00
Vlad 37482d3b69 Replace UITableViewRowAction with UIContextualAction 2020-12-26 10:31:38 +03:00
Loupehope 2cc161f0c0
Merge pull request #5 from maxsokolov/master
Merge source master
2020-12-26 10:16:07 +03:00
Max Sokolov 8bf4840d9d bump to 2.11.0 2020-05-04 08:11:57 -04:00
Max Sokolov 3b266fb7c7
Merge pull request #98 from mrtokii/feature/ios13_actions
Add support for iOS 13 actions
2020-05-04 08:06:36 -04:00
mrtokii eb93fe253c Add multiple selection actions & context menu action 2020-05-03 16:25:30 +03:00
Max Sokolov 44c55d2f05
Merge pull request #96 from DmitryFrishbuter/readme-patch
Fix typo in README.md
2019-10-05 15:10:11 -04:00
Dmitry Frishbuter efe99eeb46 Fix typo in README.md 2019-10-05 21:57:35 +06:00
Max Sokolov a0658f0b2e fix travis-ci 2019-09-29 10:03:45 -04:00
Max Sokolov 065cd9ace3 fix travis-ci 2019-09-29 09:56:11 -04:00
Max Sokolov c3652eec6f bump podspec 2019-09-29 09:51:33 -04:00
Max Sokolov 01bf1e01e3 support swift 5.1 and xcode 11 2019-09-29 09:50:40 -04:00
Max Sokolov 45aee4522d
Merge pull request #95 from bellebethcooper/master
Updated Swift tools version and added missing requirements
2019-09-19 16:45:06 -04:00
bellebethcooper f39e7ac602
Updated Swift tools version and added missing requirements 2019-09-07 15:49:07 +10:00
Max Sokolov dc1a924a80 drop iOS 9 checks on ci 2019-06-25 14:45:02 +03:00
Max Sokolov 402757c41f drop iOS 9 checks on ci 2019-06-25 14:36:47 +03:00
Max Sokolov d6520346c3
Merge pull request #94 from dmertsalov/master
Add accessoryButton action support
2019-05-29 09:34:05 +03:00
Denis 959032a03f Add accessoryButton action support 2019-05-27 11:01:35 +03:00
Max Sokolov 00de0cd809
Merge pull request #93 from IntelBohdan/master
added: willDeselect
2019-05-10 19:35:09 +03:00
Bogdan Kurpakov 337175c507 added: willDeselect 2019-05-09 11:10:31 +02:00
Max Sokolov a4bacd2c16 fix travis ci 2019-04-04 23:40:25 +03:00
Max Sokolov 603264a6d1 fix travis ci 2019-04-04 23:31:40 +03:00
Max Sokolov 1d4fdaad0d update readme 2019-04-04 23:27:25 +03:00
Max Sokolov f5ad500ba4 support swift 5.0, bump to 2.9.0 2019-04-04 23:26:15 +03:00
Ivan Zinovyev 1b4a988b35
Merge pull request #4 from TouchInstinct/expandable_states
Expandable states
2019-01-22 13:06:16 +03:00
Ivan Zinovyev f8f2ca6852 Fix indentation 2019-01-22 03:16:40 +03:00
Ivan Zinovyev ff18a4d8b8 Add Expandable States 2019-01-22 03:00:41 +03:00
Ivan Zinovyev d098691621 Merge remote-tracking branch 'maxsokolov/master' into expandable_states 2019-01-22 02:51:16 +03:00
Max Sokolov 8b6319d510 bump to 2.8.1 2019-01-10 18:35:53 +03:00
Max Sokolov b049864758 fix crash on iOS 10.3.1 2019-01-10 18:35:35 +03:00
15 changed files with 297 additions and 121 deletions

View File

@ -1 +1 @@
4.2
5.7

View File

@ -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

View File

@ -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.

View File

@ -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;
};

View File

@ -1,5 +1,19 @@
// swift-tools-version:5.7
import PackageDescription
let package = Package(
name: "TableKit"
)
name: "TableKit",
products: [
.library(
name: "TableKit",
targets: ["TableKit"]),
],
targets: [
.target(
name: "TableKit",
path: "Sources")
]
)

View File

@ -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_4.2-compatible-4BC51D.svg?style=flat" alt="Swift 4.2 compatible" /></a>
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/Swift_5.1-compatible-4BC51D.svg?style=flat" alt="Swift 5.1 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-2.8.0-blue.svg" alt="CocoaPods compatible" /></a>
<a href="https://cocoapods.org/pods/tablekit"><img src="https://img.shields.io/badge/pod-2.11.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>
@ -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

View File

@ -1,70 +1,96 @@
import UIKit
public extension TimeInterval {
static let defaultExpandableAnimationDuration: TimeInterval = 0.3
}
public protocol Expandable {
associatedtype ViewModelType: ExpandableCellViewModel
var viewModel: ViewModelType? { get }
func configureAppearance(isCollapsed: Bool)
func configure(state: ExpandableState)
}
extension Expandable where Self: UITableViewCell & ConfigurableCell {
public func initState() {
guard let viewModel = viewModel else {
return
}
changeState(isCollapsed: viewModel.isCollapsed)
changeState(expandableState: viewModel.expandableState)
}
private func changeState(isCollapsed: Bool) {
private func changeState(expandableState: ExpandableState) {
// layout to get right frames, frame of bottom subview can be used to get expanded height
setNeedsLayout()
layoutIfNeeded()
// apply changes
configureAppearance(isCollapsed: isCollapsed)
configure(state: expandableState)
layoutIfNeeded()
}
public func toggleState(animated: Bool = true,
animationDuration: TimeInterval = 0.3) {
guard let tableView = tableView,
let viewModel = viewModel else {
animationDuration: TimeInterval = .defaultExpandableAnimationDuration) {
guard let viewModel = viewModel,
let stateIndex = viewModel.availableStates.firstIndex(where: { $0 == viewModel.expandableState }) else {
return
}
let targetState = stateIndex == viewModel.availableStates.count - 1
? viewModel.availableStates[0]
: viewModel.availableStates[stateIndex + 1]
transition(to: targetState,
animated: animated,
animationDuration: animationDuration)
}
public func transition(to state: ExpandableState,
animated: Bool = true,
animationDuration: TimeInterval = .defaultExpandableAnimationDuration) {
guard let tableView = tableView,
let viewModel = viewModel,
viewModel.expandableState != state else {
return
}
let contentOffset = tableView.contentOffset
if animated {
UIView.animate(withDuration: animationDuration,
animations: { [weak self] in
self?.applyChanges(isCollapsed: !viewModel.isCollapsed)
self?.applyChanges(expandableState: state)
}, completion: { _ in
viewModel.isCollapsed.toggle()
viewModel.expandableState = state
})
} else {
applyChanges(isCollapsed: !viewModel.isCollapsed)
viewModel.isCollapsed.toggle()
applyChanges(expandableState: state)
viewModel.expandableState = state
}
tableView.beginUpdates()
tableView.endUpdates()
tableView.setContentOffset(contentOffset, animated: false)
}
private func applyChanges(isCollapsed: Bool) {
changeState(isCollapsed: isCollapsed)
public func applyChanges(expandableState: ExpandableState) {
changeState(expandableState: expandableState)
if let indexPath = indexPath,
let tableDirector = (tableView?.delegate as? TableDirector),
let cellHeightCalculator = tableDirector.rowHeightCalculator as? ExpandableCellHeightCalculator {
cellHeightCalculator.updateCached(height: height(layoutType: Self.layoutType), for: indexPath)
cellHeightCalculator.updateCached(height: expandableState.height ?? height(layoutType: Self.layoutType), for: indexPath)
}
}
}

View File

@ -1,5 +1,15 @@
public protocol ExpandableCellViewModel: class {
var isCollapsed: Bool { get set }
public protocol ExpandableCellViewModel: AnyObject {
var expandableState: ExpandableState { get set }
var availableStates: [ExpandableState] { get }
}
public extension ExpandableCellViewModel {
var availableStates: [ExpandableState] {
return [.collapsed, .expanded]
}
}

View File

@ -0,0 +1,41 @@
import UIKit
public enum ExpandableState {
case collapsed
case expanded
case height(value: CGFloat)
}
extension ExpandableState: Equatable { }
extension ExpandableState {
public var isCollapsed: Bool {
guard case .collapsed = self else {
return false
}
return true
}
public var isExpanded: Bool {
guard case .expanded = self else {
return false
}
return true
}
public var height: CGFloat? {
guard case let .height(value: height) = self else {
return nil
}
return height
}
}

View File

@ -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,9 +179,7 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
}
open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard !sections.isEmpty else {
return 0
}
guard section < sections.count else { return 0 }
return sections[section].numberOfRows
}
@ -200,51 +205,39 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
// MARK: UITableViewDataSource - section setup
open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
guard !sections.isEmpty else {
return nil
}
guard section < sections.count else { return nil }
return sections[section].headerTitle
}
open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
guard !sections.isEmpty else {
return nil
}
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 !sections.isEmpty else {
return nil
}
guard section < sections.count else { return nil }
return sections[section].headerView
}
open func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
guard !sections.isEmpty else {
return nil
}
guard section < sections.count else { return nil }
return sections[section].footerView
}
open func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
guard !sections.isEmpty else {
return UITableView.automaticDimension
}
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 !sections.isEmpty else {
return UITableView.automaticDimension
}
guard section < sections.count else { return 0 }
let section = sections[section]
return section.footerHeight
@ -316,13 +309,62 @@ 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)
}
open func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
return sections[indexPath.section].rows[indexPath.row].editingActions
open func tableView(_ tableView: UITableView,
leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let currentRow = sections[indexPath.section].rows[indexPath.row]
let configuration = UISwipeActionsConfiguration(actions: currentRow.leadingContextualActions)
configuration.performsFirstActionWithFullSwipe = currentRow.performsFirstActionWithFullSwipe
return configuration
}
open func tableView(_ tableView: UITableView,
trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let currentRow = sections[indexPath.section].rows[indexPath.row]
let configuration = UISwipeActionsConfiguration(actions: currentRow.trailingContextualActions)
configuration.performsFirstActionWithFullSwipe = currentRow.performsFirstActionWithFullSwipe
return configuration
}
open func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
@ -354,42 +396,47 @@ 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
extension TableDirector {
@discardableResult
open func append(section: TableSection) -> Self {
public func append(section: TableSection) -> Self {
append(sections: [section])
return self
}
@discardableResult
open func append(sections: [TableSection]) -> Self {
public func append(sections: [TableSection]) -> Self {
self.sections.append(contentsOf: sections)
return self
}
@discardableResult
open func append(rows: [Row]) -> Self {
public func append(rows: [Row]) -> Self {
append(section: TableSection(rows: rows))
return self
}
@discardableResult
open func insert(section: TableSection, atIndex index: Int) -> Self {
public func insert(section: TableSection, atIndex index: Int) -> Self {
sections.insert(section, at: index)
return self
}
@discardableResult
open func replaceSection(at index: Int, with section: TableSection) -> Self {
public func replaceSection(at index: Int, with section: TableSection) -> Self {
if index < sections.count {
sections[index] = section
}
@ -397,20 +444,20 @@ extension TableDirector {
}
@discardableResult
open func delete(sectionAt index: Int) -> Self {
public func delete(sectionAt index: Int) -> Self {
sections.remove(at: index)
return self
}
@discardableResult
open func remove(sectionAt index: Int) -> Self {
public func remove(sectionAt index: Int) -> Self {
return delete(sectionAt: index)
}
@discardableResult
open func clear() -> Self {
public func clear() -> Self {
rowHeightCalculator?.invalidate()
sections.removeAll()
@ -420,7 +467,7 @@ extension TableDirector {
// MARK: - deprecated methods
@available(*, deprecated, message: "Use 'delete(sectionAt:)' method instead")
@discardableResult
open func delete(index: Int) -> Self {
public func delete(index: Int) -> Self {
sections.remove(at: index)
return self

View File

@ -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 {
@ -36,8 +37,10 @@ public protocol RowConfigurable {
}
public protocol RowActionable {
var editingActions: [UITableViewRowAction]? { get }
var leadingContextualActions: [UIContextualAction] { get }
var trailingContextualActions: [UIContextualAction] { get }
var performsFirstActionWithFullSwipe: Bool { get }
func isEditingAllowed(forIndexPath indexPath: IndexPath) -> Bool
func invoke(
@ -71,9 +74,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 +87,8 @@ public enum TableRowActionType {
case canMove
case canMoveTo
case move
case showContextMenu
case accessoryButtonTap
case custom(String)
var key: String {

View File

@ -21,10 +21,21 @@
import UIKit
open class TableRow<CellType: ConfigurableCell>: Row where CellType: UITableViewCell {
public let item: CellType.CellData
private lazy var actions = [String: [TableRowAction<CellType>]]()
private(set) open var editingActions: [UITableViewRowAction]?
open var leadingContextualActions: [UIContextualAction] {
[]
}
open var trailingContextualActions: [UIContextualAction] {
[]
}
open var performsFirstActionWithFullSwipe: Bool {
false
}
open var hashValue: Int {
return ObjectIdentifier(self).hashValue
@ -50,10 +61,11 @@ open class TableRow<CellType: ConfigurableCell>: Row where CellType: UITableView
return CellType.self
}
public init(item: CellType.CellData, actions: [TableRowAction<CellType>]? = nil, editingActions: [UITableViewRowAction]? = nil) {
public init(item: CellType.CellData,
actions: [TableRowAction<CellType>]? = nil) {
self.item = item
self.editingActions = editingActions
actions?.forEach { on($0) }
}
@ -81,7 +93,10 @@ open class TableRow<CellType: ConfigurableCell>: Row where CellType: UITableView
if actions[TableRowActionType.canEdit.key] != nil {
return invoke(action: .canEdit, cell: nil, path: indexPath) as? Bool ?? false
}
return editingActions?.isEmpty == false || actions[TableRowActionType.clickDelete.key] != nil
return !leadingContextualActions.isEmpty
|| !trailingContextualActions.isEmpty
|| actions[TableRowActionType.clickDelete.key] != nil
}
// MARK: - actions -
@ -117,7 +132,7 @@ open class TableRow<CellType: ConfigurableCell>: Row where CellType: UITableView
open func removeAction(forActionId actionId: String) {
for (key, value) in actions {
if let actionIndex = value.index(where: { $0.id == actionId }) {
if let actionIndex = value.firstIndex(where: { $0.id == actionId }) {
actions[key]?.remove(at: actionIndex)
}
}

View File

@ -2,16 +2,16 @@ Pod::Spec.new do |s|
s.name = 'TableKit'
s.module_name = 'TableKit'
s.version = '2.8.0'
s.version = '2.12'
s.homepage = 'https://github.com/maxsokolov/TableKit'
s.homepage = 'https://git.svc.touchin.ru/TouchInstinct/TableKit'
s.summary = 'Type-safe declarative table views with Swift.'
s.author = { 'Max Sokolov' => 'i@maxsokolov.net' }
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.platforms = { :ios => '8.0' }
s.ios.deployment_target = '8.0'
s.platforms = { :ios => '12.0' }
s.ios.deployment_target = '12.0'
s.source_files = 'Sources/*.swift'
s.source = { :git => 'https://github.com/maxsokolov/TableKit.git', :tag => s.version }
s.source = { :git => 'https://git.svc.touchin.ru/TouchInstinct/TableKit.git', :tag => s.version }
end

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
2CBFA2F521F692F100147B56 /* ExpandableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CBFA2F421F692F100147B56 /* ExpandableState.swift */; };
3201E78421BE9DE1001DF9E7 /* ExpandableCellHeightCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3201E78321BE9DE1001DF9E7 /* ExpandableCellHeightCalculator.swift */; };
3201E78621BE9E25001DF9E7 /* UITableViewCell+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3201E78521BE9E25001DF9E7 /* UITableViewCell+Extensions.swift */; };
3201E78821BE9EB2001DF9E7 /* Expandable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3201E78721BE9EB2001DF9E7 /* Expandable.swift */; };
@ -37,6 +38,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
2CBFA2F421F692F100147B56 /* ExpandableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpandableState.swift; sourceTree = "<group>"; };
3201E78321BE9DE1001DF9E7 /* ExpandableCellHeightCalculator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExpandableCellHeightCalculator.swift; sourceTree = "<group>"; };
3201E78521BE9E25001DF9E7 /* UITableViewCell+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableViewCell+Extensions.swift"; sourceTree = "<group>"; };
3201E78721BE9EB2001DF9E7 /* Expandable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Expandable.swift; sourceTree = "<group>"; };
@ -115,6 +117,7 @@
3201E78721BE9EB2001DF9E7 /* Expandable.swift */,
3201E78921BE9ED4001DF9E7 /* ExpandableCellViewModel.swift */,
32BDFE9E21C167F400D0BBB4 /* LayoutType.swift */,
2CBFA2F421F692F100147B56 /* ExpandableState.swift */,
);
path = Sources;
sourceTree = "<group>";
@ -210,6 +213,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = DA9EA74C1D0B679A0021F650;
@ -250,6 +254,7 @@
DA9EA7AF1D0EC2C90021F650 /* ConfigurableCell.swift in Sources */,
DA9EA7B31D0EC2C90021F650 /* TableDirector.swift in Sources */,
3201E78821BE9EB2001DF9E7 /* Expandable.swift in Sources */,
2CBFA2F521F692F100147B56 /* ExpandableState.swift in Sources */,
DA9EA7B71D0EC2C90021F650 /* TableSection.swift in Sources */,
DA9EA7B01D0EC2C90021F650 /* TablePrototypeCellHeightCalculator.swift in Sources */,
3201E78421BE9DE1001DF9E7 /* ExpandableCellHeightCalculator.swift in Sources */,
@ -335,7 +340,7 @@
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
@ -388,7 +393,7 @@
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
@ -413,7 +418,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
@ -433,7 +438,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKit;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Release;
};
@ -445,7 +450,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
@ -457,7 +462,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Release;
};

View File

@ -74,7 +74,10 @@ class TableKitTests: XCTestCase {
super.setUp()
testController = TestController()
testController.view.isHidden = false
testController.tableView.frame = UIScreen.main.bounds
testController.tableView.isHidden = false
testController.tableView.setNeedsLayout()
testController.tableView.layoutIfNeeded()
}
override func tearDown() {