Compare commits
1 Commits
master
...
fix/reload
| Author | SHA1 | Date |
|---|---|---|
|
|
35084d4224 |
|
|
@ -1 +1 @@
|
|||
5.7
|
||||
4.2
|
||||
12
.travis.yml
12
.travis.yml
|
|
@ -1,5 +1,5 @@
|
|||
language: objective-c
|
||||
osx_image: xcode11
|
||||
osx_image: xcode10
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
|
@ -7,15 +7,17 @@ env:
|
|||
global:
|
||||
- LC_CTYPE=en_US.UTF-8
|
||||
- LANG=en_US.UTF-8
|
||||
- IOS_SDK=iphonesimulator13.0
|
||||
- IOS_SDK=iphonesimulator12.0
|
||||
- SCHEME_IOS="TableKit"
|
||||
- PROJECT_FRAMEWORK="TableKit.xcodeproj"
|
||||
|
||||
matrix:
|
||||
- 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=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=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
|
||||
|
|
|
|||
|
|
@ -2,14 +2,6 @@
|
|||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -248,7 +248,6 @@
|
|||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
English,
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
|
|
@ -378,7 +377,7 @@
|
|||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -426,7 +425,7 @@
|
|||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
|
|
@ -444,7 +443,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.demo;
|
||||
PRODUCT_NAME = TableKitDemo;
|
||||
PROVISIONING_PROFILE = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -461,7 +460,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.demo;
|
||||
PRODUCT_NAME = TableKitDemo;
|
||||
PROVISIONING_PROFILE = "";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,19 +1,5 @@
|
|||
// swift-tools-version:5.7
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "TableKit",
|
||||
|
||||
products: [
|
||||
.library(
|
||||
name: "TableKit",
|
||||
targets: ["TableKit"]),
|
||||
],
|
||||
|
||||
targets: [
|
||||
.target(
|
||||
name: "TableKit",
|
||||
path: "Sources")
|
||||
]
|
||||
)
|
||||
name: "TableKit"
|
||||
)
|
||||
|
|
@ -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_5.1-compatible-4BC51D.svg?style=flat" alt="Swift 5.1 compatible" /></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://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.11.0-blue.svg" alt="CocoaPods 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>
|
||||
<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 matches cell's xib name:
|
||||
TableKit can register your cells in a table view automatically. In case if your reusable cell id mathces cell's xib name:
|
||||
|
||||
```ruby
|
||||
MyTableViewCell.swift
|
||||
|
|
|
|||
|
|
@ -1,96 +1,70 @@
|
|||
import UIKit
|
||||
|
||||
public extension TimeInterval {
|
||||
|
||||
static let defaultExpandableAnimationDuration: TimeInterval = 0.3
|
||||
|
||||
}
|
||||
|
||||
public protocol Expandable {
|
||||
|
||||
|
||||
associatedtype ViewModelType: ExpandableCellViewModel
|
||||
|
||||
|
||||
var viewModel: ViewModelType? { get }
|
||||
|
||||
func configure(state: ExpandableState)
|
||||
|
||||
|
||||
func configureAppearance(isCollapsed: Bool)
|
||||
|
||||
}
|
||||
|
||||
extension Expandable where Self: UITableViewCell & ConfigurableCell {
|
||||
|
||||
|
||||
public func initState() {
|
||||
guard let viewModel = viewModel else {
|
||||
return
|
||||
}
|
||||
|
||||
changeState(expandableState: viewModel.expandableState)
|
||||
|
||||
changeState(isCollapsed: viewModel.isCollapsed)
|
||||
}
|
||||
|
||||
private func changeState(expandableState: ExpandableState) {
|
||||
|
||||
private func changeState(isCollapsed: Bool) {
|
||||
// layout to get right frames, frame of bottom subview can be used to get expanded height
|
||||
setNeedsLayout()
|
||||
layoutIfNeeded()
|
||||
|
||||
|
||||
// apply changes
|
||||
configure(state: expandableState)
|
||||
configureAppearance(isCollapsed: isCollapsed)
|
||||
layoutIfNeeded()
|
||||
}
|
||||
|
||||
|
||||
public func toggleState(animated: Bool = true,
|
||||
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) {
|
||||
|
||||
animationDuration: TimeInterval = 0.3) {
|
||||
|
||||
guard let tableView = tableView,
|
||||
let viewModel = viewModel,
|
||||
viewModel.expandableState != state else {
|
||||
let viewModel = viewModel else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
let contentOffset = tableView.contentOffset
|
||||
|
||||
|
||||
if animated {
|
||||
UIView.animate(withDuration: animationDuration,
|
||||
animations: { [weak self] in
|
||||
self?.applyChanges(expandableState: state)
|
||||
self?.applyChanges(isCollapsed: !viewModel.isCollapsed)
|
||||
}, completion: { _ in
|
||||
viewModel.expandableState = state
|
||||
viewModel.isCollapsed.toggle()
|
||||
})
|
||||
} else {
|
||||
applyChanges(expandableState: state)
|
||||
viewModel.expandableState = state
|
||||
applyChanges(isCollapsed: !viewModel.isCollapsed)
|
||||
viewModel.isCollapsed.toggle()
|
||||
}
|
||||
|
||||
|
||||
tableView.beginUpdates()
|
||||
tableView.endUpdates()
|
||||
|
||||
|
||||
tableView.setContentOffset(contentOffset, animated: false)
|
||||
}
|
||||
|
||||
public func applyChanges(expandableState: ExpandableState) {
|
||||
changeState(expandableState: expandableState)
|
||||
|
||||
|
||||
private func applyChanges(isCollapsed: Bool) {
|
||||
changeState(isCollapsed: isCollapsed)
|
||||
|
||||
if let indexPath = indexPath,
|
||||
let tableDirector = (tableView?.delegate as? TableDirector),
|
||||
let cellHeightCalculator = tableDirector.rowHeightCalculator as? ExpandableCellHeightCalculator {
|
||||
cellHeightCalculator.updateCached(height: expandableState.height ?? height(layoutType: Self.layoutType), for: indexPath)
|
||||
cellHeightCalculator.updateCached(height: height(layoutType: Self.layoutType), for: indexPath)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,5 @@
|
|||
public protocol ExpandableCellViewModel: AnyObject {
|
||||
|
||||
var expandableState: ExpandableState { get set }
|
||||
|
||||
var availableStates: [ExpandableState] { get }
|
||||
|
||||
}
|
||||
public protocol ExpandableCellViewModel: class {
|
||||
|
||||
var isCollapsed: Bool { get set }
|
||||
|
||||
public extension ExpandableCellViewModel {
|
||||
|
||||
var availableStates: [ExpandableState] {
|
||||
return [.collapsed, .expanded]
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -95,14 +95,6 @@ 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(
|
||||
|
|
@ -110,13 +102,15 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
|
|||
cell: UITableViewCell?, indexPath: IndexPath,
|
||||
userInfo: [AnyHashable: Any]? = nil) -> Any?
|
||||
{
|
||||
guard let row = row(at: indexPath) else { return nil }
|
||||
return row.invoke(
|
||||
action: action,
|
||||
cell: cell,
|
||||
path: indexPath,
|
||||
userInfo: userInfo
|
||||
)
|
||||
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
|
||||
}
|
||||
|
||||
open override func responds(to selector: Selector) -> Bool {
|
||||
|
|
@ -131,8 +125,7 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
|
|||
|
||||
// MARK: - Internal
|
||||
func hasAction(_ action: TableRowActionType, atIndexPath indexPath: IndexPath) -> Bool {
|
||||
guard let row = row(at: indexPath) else { return false }
|
||||
return row.has(action: action)
|
||||
return sections[indexPath.section].rows[indexPath.row].has(action: action)
|
||||
}
|
||||
|
||||
@objc
|
||||
|
|
@ -179,7 +172,9 @@ open class TableDirector: NSObject, UITableViewDataSource, UITableViewDelegate {
|
|||
}
|
||||
|
||||
open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
guard section < sections.count else { return 0 }
|
||||
guard !sections.isEmpty else {
|
||||
return 0
|
||||
}
|
||||
|
||||
return sections[section].numberOfRows
|
||||
}
|
||||
|
|
@ -205,39 +200,51 @@ 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 }
|
||||
guard !sections.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sections[section].headerTitle
|
||||
}
|
||||
|
||||
open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
guard section < sections.count else { return nil }
|
||||
guard !sections.isEmpty 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 }
|
||||
guard !sections.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sections[section].headerView
|
||||
}
|
||||
|
||||
open func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
||||
guard section < sections.count else { return nil }
|
||||
guard !sections.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return sections[section].footerView
|
||||
}
|
||||
|
||||
open func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
guard section < sections.count else { return 0 }
|
||||
guard !sections.isEmpty else {
|
||||
return UITableView.automaticDimension
|
||||
}
|
||||
|
||||
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 }
|
||||
guard !sections.isEmpty else {
|
||||
return UITableView.automaticDimension
|
||||
}
|
||||
|
||||
let section = sections[section]
|
||||
return section.footerHeight
|
||||
|
|
@ -309,62 +316,13 @@ 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,
|
||||
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, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
|
||||
return sections[indexPath.section].rows[indexPath.row].editingActions
|
||||
}
|
||||
|
||||
open func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
|
||||
|
|
@ -396,47 +354,42 @@ 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
|
||||
public func append(section: TableSection) -> Self {
|
||||
open func append(section: TableSection) -> Self {
|
||||
|
||||
append(sections: [section])
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func append(sections: [TableSection]) -> Self {
|
||||
|
||||
open func append(sections: [TableSection]) -> Self {
|
||||
|
||||
self.sections.append(contentsOf: sections)
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func append(rows: [Row]) -> Self {
|
||||
|
||||
open func append(rows: [Row]) -> Self {
|
||||
|
||||
append(section: TableSection(rows: rows))
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func insert(section: TableSection, atIndex index: Int) -> Self {
|
||||
|
||||
open func insert(section: TableSection, atIndex index: Int) -> Self {
|
||||
|
||||
sections.insert(section, at: index)
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func replaceSection(at index: Int, with section: TableSection) -> Self {
|
||||
|
||||
open func replaceSection(at index: Int, with section: TableSection) -> Self {
|
||||
|
||||
if index < sections.count {
|
||||
sections[index] = section
|
||||
}
|
||||
|
|
@ -444,20 +397,20 @@ extension TableDirector {
|
|||
}
|
||||
|
||||
@discardableResult
|
||||
public func delete(sectionAt index: Int) -> Self {
|
||||
|
||||
open func delete(sectionAt index: Int) -> Self {
|
||||
|
||||
sections.remove(at: index)
|
||||
return self
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func remove(sectionAt index: Int) -> Self {
|
||||
open func remove(sectionAt index: Int) -> Self {
|
||||
return delete(sectionAt: index)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func clear() -> Self {
|
||||
|
||||
open func clear() -> Self {
|
||||
|
||||
rowHeightCalculator?.invalidate()
|
||||
sections.removeAll()
|
||||
|
||||
|
|
@ -467,7 +420,7 @@ extension TableDirector {
|
|||
// MARK: - deprecated methods
|
||||
@available(*, deprecated, message: "Use 'delete(sectionAt:)' method instead")
|
||||
@discardableResult
|
||||
public func delete(index: Int) -> Self {
|
||||
open func delete(index: Int) -> Self {
|
||||
|
||||
sections.remove(at: index)
|
||||
return self
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ struct TableKitNotifications {
|
|||
public struct TableKitUserInfoKeys {
|
||||
public static let CellMoveDestinationIndexPath = "TableKitCellMoveDestinationIndexPath"
|
||||
public static let CellCanMoveProposedIndexPath = "CellCanMoveProposedIndexPath"
|
||||
public static let ContextMenuInvokePoint = "ContextMenuInvokePoint"
|
||||
}
|
||||
|
||||
public protocol RowConfigurable {
|
||||
|
|
@ -37,10 +36,8 @@ public protocol RowConfigurable {
|
|||
}
|
||||
|
||||
public protocol RowActionable {
|
||||
var leadingContextualActions: [UIContextualAction] { get }
|
||||
var trailingContextualActions: [UIContextualAction] { get }
|
||||
var performsFirstActionWithFullSwipe: Bool { get }
|
||||
|
||||
|
||||
var editingActions: [UITableViewRowAction]? { get }
|
||||
func isEditingAllowed(forIndexPath indexPath: IndexPath) -> Bool
|
||||
|
||||
func invoke(
|
||||
|
|
@ -74,12 +71,9 @@ 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
|
||||
|
|
@ -87,8 +81,6 @@ public enum TableRowActionType {
|
|||
case canMove
|
||||
case canMoveTo
|
||||
case move
|
||||
case showContextMenu
|
||||
case accessoryButtonTap
|
||||
case custom(String)
|
||||
|
||||
var key: String {
|
||||
|
|
|
|||
|
|
@ -21,21 +21,10 @@
|
|||
import UIKit
|
||||
|
||||
open class TableRow<CellType: ConfigurableCell>: Row where CellType: UITableViewCell {
|
||||
|
||||
|
||||
public let item: CellType.CellData
|
||||
private lazy var actions = [String: [TableRowAction<CellType>]]()
|
||||
|
||||
open var leadingContextualActions: [UIContextualAction] {
|
||||
[]
|
||||
}
|
||||
|
||||
open var trailingContextualActions: [UIContextualAction] {
|
||||
[]
|
||||
}
|
||||
|
||||
open var performsFirstActionWithFullSwipe: Bool {
|
||||
false
|
||||
}
|
||||
private(set) open var editingActions: [UITableViewRowAction]?
|
||||
|
||||
open var hashValue: Int {
|
||||
return ObjectIdentifier(self).hashValue
|
||||
|
|
@ -61,11 +50,10 @@ open class TableRow<CellType: ConfigurableCell>: Row where CellType: UITableView
|
|||
return CellType.self
|
||||
}
|
||||
|
||||
public init(item: CellType.CellData,
|
||||
actions: [TableRowAction<CellType>]? = nil) {
|
||||
public init(item: CellType.CellData, actions: [TableRowAction<CellType>]? = nil, editingActions: [UITableViewRowAction]? = nil) {
|
||||
|
||||
self.item = item
|
||||
|
||||
self.editingActions = editingActions
|
||||
actions?.forEach { on($0) }
|
||||
}
|
||||
|
||||
|
|
@ -93,10 +81,7 @@ 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 !leadingContextualActions.isEmpty
|
||||
|| !trailingContextualActions.isEmpty
|
||||
|| actions[TableRowActionType.clickDelete.key] != nil
|
||||
return editingActions?.isEmpty == false || actions[TableRowActionType.clickDelete.key] != nil
|
||||
}
|
||||
|
||||
// MARK: - actions -
|
||||
|
|
@ -132,7 +117,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.firstIndex(where: { $0.id == actionId }) {
|
||||
if let actionIndex = value.index(where: { $0.id == actionId }) {
|
||||
actions[key]?.remove(at: actionIndex)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ Pod::Spec.new do |s|
|
|||
s.name = 'TableKit'
|
||||
s.module_name = 'TableKit'
|
||||
|
||||
s.version = '2.12'
|
||||
s.version = '2.8.0'
|
||||
|
||||
s.homepage = 'https://git.svc.touchin.ru/TouchInstinct/TableKit'
|
||||
s.homepage = 'https://github.com/maxsokolov/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 => '12.0' }
|
||||
s.ios.deployment_target = '12.0'
|
||||
s.platforms = { :ios => '8.0' }
|
||||
s.ios.deployment_target = '8.0'
|
||||
|
||||
s.source_files = 'Sources/*.swift'
|
||||
s.source = { :git => 'https://git.svc.touchin.ru/TouchInstinct/TableKit.git', :tag => s.version }
|
||||
s.source = { :git => 'https://github.com/maxsokolov/TableKit.git', :tag => s.version }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
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 */; };
|
||||
|
|
@ -38,7 +37,6 @@
|
|||
/* 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>"; };
|
||||
|
|
@ -117,7 +115,6 @@
|
|||
3201E78721BE9EB2001DF9E7 /* Expandable.swift */,
|
||||
3201E78921BE9ED4001DF9E7 /* ExpandableCellViewModel.swift */,
|
||||
32BDFE9E21C167F400D0BBB4 /* LayoutType.swift */,
|
||||
2CBFA2F421F692F100147B56 /* ExpandableState.swift */,
|
||||
);
|
||||
path = Sources;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -213,7 +210,6 @@
|
|||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
English,
|
||||
en,
|
||||
);
|
||||
mainGroup = DA9EA74C1D0B679A0021F650;
|
||||
|
|
@ -254,7 +250,6 @@
|
|||
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 */,
|
||||
|
|
@ -340,7 +335,7 @@
|
|||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
|
|
@ -393,7 +388,7 @@
|
|||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
|
@ -418,7 +413,7 @@
|
|||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -438,7 +433,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKit;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
@ -450,7 +445,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
|
@ -462,7 +457,7 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.tablekit.TableKitTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
SWIFT_VERSION = 4.2;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -74,10 +74,7 @@ class TableKitTests: XCTestCase {
|
|||
super.setUp()
|
||||
|
||||
testController = TestController()
|
||||
testController.tableView.frame = UIScreen.main.bounds
|
||||
testController.tableView.isHidden = false
|
||||
testController.tableView.setNeedsLayout()
|
||||
testController.tableView.layoutIfNeeded()
|
||||
testController.view.isHidden = false
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue