From 979a30febf7cf1460b5964f54bd2d8584162ed15 Mon Sep 17 00:00:00 2001 From: Igor Date: Sun, 8 Oct 2017 17:17:45 +0300 Subject: [PATCH 01/24] Add base cell --- LeadKit.xcodeproj/project.pbxproj | 49 ++++++- .../Views/BaseCell/AnyBaseTableRow.swift | 63 ++++++++ Sources/Classes/Views/BaseCell/BaseCell.swift | 138 ++++++++++++++++++ .../Views/BaseCell/BaseCellViewModel.swift | 89 +++++++++++ .../Classes/Views/BaseCell/EmptyCellRow.swift | 50 +++++++ 5 files changed, 388 insertions(+), 1 deletion(-) create mode 100644 Sources/Classes/Views/BaseCell/AnyBaseTableRow.swift create mode 100644 Sources/Classes/Views/BaseCell/BaseCell.swift create mode 100644 Sources/Classes/Views/BaseCell/BaseCellViewModel.swift create mode 100644 Sources/Classes/Views/BaseCell/EmptyCellRow.swift diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index 32475e1f..b28bad93 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -384,6 +384,22 @@ 67E6C2371EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 67E6C2381EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; }; + A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; + A6E0DDDF1F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; + A6E0DDE01F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; + A6E0DDE11F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; + A6E0DDE21F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; + A6E0DDE31F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; + A6E0DDE41F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; + A6E0DDE51F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; + A6E0DDE61F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; + A6E0DDE71F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; + A6E0DDE81F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; + A6E0DDE91F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; + A6E0DDEA1F8A6970002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; + A6E0DDEB1F8A6970002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; + A6E0DDEC1F8A6970002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; + A6E0DDED1F8A6970002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */; }; A6F32C0A1F6EBE5B00AC08EE /* String+LocalizedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */; }; A6F32C0B1F6EBE5C00AC08EE /* String+LocalizedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */; }; @@ -576,6 +592,10 @@ 887F99C5326BD220C2811BD6 /* Pods_LeadKit_LeadKit_iOS_Extensions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_iOS_Extensions.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 95E457F1241D136396FC2420 /* Pods_LeadKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9966FB938D114F79F71AE037 /* Pods-LeadKit-LeadKit iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit-LeadKit iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit-LeadKit iOS/Pods-LeadKit-LeadKit iOS.release.xcconfig"; sourceTree = ""; }; + A66428A51F8A653500C6308D /* BaseCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCellViewModel.swift; sourceTree = ""; }; + A66428A61F8A653600C6308D /* BaseCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCell.swift; sourceTree = ""; }; + A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = ""; }; + A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyBaseTableRow.swift; sourceTree = ""; }; A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+LocalizedComponent.swift"; sourceTree = ""; }; A6F32C0E1F6EBE8E00AC08EE /* StringExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionTests.swift; sourceTree = ""; }; A854A36EB179651E6D0CC9FB /* Pods_LeadKit_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -718,6 +738,7 @@ 671461D41EB3396E00EAB194 /* Views */ = { isa = PBXGroup; children = ( + A66428A41F8A651700C6308D /* BaseCell */, 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */, 671461D51EB3396E00EAB194 /* XibView.swift */, ); @@ -1222,12 +1243,22 @@ path = Single; sourceTree = ""; }; + A66428A41F8A651700C6308D /* BaseCell */ = { + isa = PBXGroup; + children = ( + A66428A71F8A654600C6308D /* EmptyCellRow.swift */, + A66428A61F8A653600C6308D /* BaseCell.swift */, + A66428A51F8A653500C6308D /* BaseCellViewModel.swift */, + A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */, + ); + path = BaseCell; + sourceTree = ""; + }; A6F32C0D1F6EBE7700AC08EE /* Extensions */ = { isa = PBXGroup; children = ( A6F32C0E1F6EBE8E00AC08EE /* StringExtensionTests.swift */, ); - name = Extensions; path = Extensions; sourceTree = ""; }; @@ -2042,6 +2073,7 @@ 671462E01EB3396E00EAB194 /* UICollectionView+CellRegistration.swift in Sources */, 671462601EB3396E00EAB194 /* PaginationTableViewWrapper.swift in Sources */, 671463281EB3396E00EAB194 /* BaseViewModel.swift in Sources */, + A6E0DDDF1F8A696F002CA74E /* BaseCell.swift in Sources */, 671462AC1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */, 671463001EB3396E00EAB194 /* UIView+LoadFromNib.swift in Sources */, 6714627C1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */, @@ -2050,6 +2082,8 @@ 671462581EB3396E00EAB194 /* Log.swift in Sources */, 671462B41EB3396E00EAB194 /* PaginationTableViewWrapperDelegate+DefaultImplementation.swift in Sources */, 671462781EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, + A6E0DDE11F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */, + A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */, 671463041EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671463701EB3396E00EAB194 /* ApiRequestParameters.swift in Sources */, @@ -2075,6 +2109,7 @@ A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */, 671462881EB3396E00EAB194 /* CGFloat+Pixels.swift in Sources */, 671462941EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */, + A6E0DDE01F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, 671463641EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */, 671462481EB3396E00EAB194 /* FixedPageCursor.swift in Sources */, 671462C81EB3396E00EAB194 /* String+Localization.swift in Sources */, @@ -2110,11 +2145,15 @@ 671463CA1EB34B1E00EAB194 /* TestView.swift in Sources */, 671463C71EB34B1E00EAB194 /* PaginationViewModelTests.swift in Sources */, 671463B81EB34B1E00EAB194 /* StubCursor.swift in Sources */, + A6E0DDE41F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, 671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */, A6F32C101F6EBE9600AC08EE /* StringExtensionTests.swift in Sources */, 671463C11EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, 671463BE1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */, + A6E0DDE21F8A696F002CA74E /* EmptyCellRow.swift in Sources */, + A6E0DDE31F8A696F002CA74E /* BaseCell.swift in Sources */, 671463C41EB34B1E00EAB194 /* Post.swift in Sources */, + A6E0DDE51F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2313,6 +2352,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A6E0DDE61F8A696F002CA74E /* EmptyCellRow.swift in Sources */, 671463491EB3396E00EAB194 /* ResettableType.swift in Sources */, 671462E51EB3396E00EAB194 /* UIColor+Hex.swift in Sources */, 671462CD1EB3396E00EAB194 /* String+SizeCalculation.swift in Sources */, @@ -2352,10 +2392,12 @@ 671462E11EB3396E00EAB194 /* UICollectionView+CellRegistration.swift in Sources */, A6F32C0A1F6EBE5B00AC08EE /* String+LocalizedComponent.swift in Sources */, 671463291EB3396E00EAB194 /* BaseViewModel.swift in Sources */, + A6E0DDE71F8A696F002CA74E /* BaseCell.swift in Sources */, 671462AD1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */, 671463011EB3396E00EAB194 /* UIView+LoadFromNib.swift in Sources */, 6714627D1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */, 671463451EB3396E00EAB194 /* ObservableMappable.swift in Sources */, + A6E0DDE91F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */, 671462591EB3396E00EAB194 /* Log.swift in Sources */, 671462791EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, 671463051EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, @@ -2400,6 +2442,7 @@ 6714628D1EB3396E00EAB194 /* CGImage+Alpha.swift in Sources */, 671462751EB3396E00EAB194 /* LeadKitError.swift in Sources */, EFBE57D11EC35EF20040E00A /* Array+Extensions.swift in Sources */, + A6E0DDE81F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, 67CDEE431EB3AD1C00895905 /* NetworkService+RxLoadImage.swift in Sources */, 671462D91EB3396E00EAB194 /* TimeInterval+DateComponents.swift in Sources */, 6714638D1EB3396E00EAB194 /* SolidFillDrawingOperation.swift in Sources */, @@ -2420,11 +2463,15 @@ 671463C21EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, 671463BF1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */, 671463C51EB34B1E00EAB194 /* Post.swift in Sources */, + A6E0DDEC1F8A6970002CA74E /* BaseCellViewModel.swift in Sources */, 671463CB1EB34B1E00EAB194 /* TestView.swift in Sources */, A6F32C111F6EBE9700AC08EE /* StringExtensionTests.swift in Sources */, 671463C81EB34B1E00EAB194 /* PaginationViewModelTests.swift in Sources */, 671463BC1EB34B1E00EAB194 /* CursorTests.swift in Sources */, + A6E0DDEA1F8A6970002CA74E /* EmptyCellRow.swift in Sources */, + A6E0DDEB1F8A6970002CA74E /* BaseCell.swift in Sources */, 671463B91EB34B1E00EAB194 /* StubCursor.swift in Sources */, + A6E0DDED1F8A6970002CA74E /* AnyBaseTableRow.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/Classes/Views/BaseCell/AnyBaseTableRow.swift b/Sources/Classes/Views/BaseCell/AnyBaseTableRow.swift new file mode 100644 index 00000000..7814f12d --- /dev/null +++ b/Sources/Classes/Views/BaseCell/AnyBaseTableRow.swift @@ -0,0 +1,63 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import TableKit + +/// Class used as general placeholder for type-erasured in TableRow +private class AnyBaseTableRowHolder { + let row: Row + + init(tableRow: Row) { + row = tableRow + } +} + +/// Class used to hold resolved TableRow +private final class AnyBaseTableRowBox: AnyBaseTableRowHolder where T: BaseCell, T.T: BaseCellViewModel { + + init(tableRow: TableRow) { + super.init(tableRow: tableRow) + } + +} + +/// Class that used to configure separators when multiply cells presented in one section +/// Holds TableRow with any model inherited from BaseCellViewModel +public final class AnyBaseTableRow { + + fileprivate let anyTableRow: AnyBaseTableRowHolder + let viewModel: BaseCellViewModel + + init(tableRow: TableRow) where T: BaseCell, T.T: BaseCellViewModel { + anyTableRow = AnyBaseTableRowBox(tableRow: tableRow) + viewModel = tableRow.item + } + +} + +public extension Array where Element == AnyBaseTableRow { + + var rows: [Row] { + return map { $0.anyTableRow.row } + } + +} diff --git a/Sources/Classes/Views/BaseCell/BaseCell.swift b/Sources/Classes/Views/BaseCell/BaseCell.swift new file mode 100644 index 00000000..08ae1f97 --- /dev/null +++ b/Sources/Classes/Views/BaseCell/BaseCell.swift @@ -0,0 +1,138 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit +import TableKit + +open class BaseCell: UITableViewCell { + + func configureSeparator(with viewModel: BaseCellViewModel) { + topSeparatorInsets = viewModel.topSeparatorInsets ?? .zero + bottomSeparatorInsets = viewModel.bottomSeparatorInsets ?? .zero + } + + // MARK: - Private + + private var topView: UIView! + private var bottomView: UIView! + + // top separator + private var topViewLeftConstraint: NSLayoutConstraint! + private var topViewRightConstraint: NSLayoutConstraint! + private var topViewTopConstraint: NSLayoutConstraint! + + // bottom separator + private var bottomViewLeftConstraint: NSLayoutConstraint! + private var bottomViewRightConstraint: NSLayoutConstraint! + private var bottomViewBottomConstraint: NSLayoutConstraint! + + // insets + private var topSeparatorInsets: UIEdgeInsets = .zero + private var bottomSeparatorInsets: UIEdgeInsets = .zero + + override open func updateConstraints() { + topViewTopConstraint.constant = topSeparatorInsets.top + topViewLeftConstraint.constant = topSeparatorInsets.left + topViewRightConstraint.constant = topSeparatorInsets.right + + bottomViewLeftConstraint.constant = bottomSeparatorInsets.left + bottomViewRightConstraint.constant = bottomSeparatorInsets.right + bottomViewBottomConstraint.constant = bottomSeparatorInsets.bottom + + super.updateConstraints() + } + + override open func awakeFromNib() { + super.awakeFromNib() + + configureLineViews() + configureSeparator(with: .none) + } + + private func configureSeparator(with separatorType: CellSeparatorType) { + topView.isHidden = separatorType.topIsHidden + bottomView.isHidden = separatorType.bottomIsHidden + + setNeedsUpdateConstraints() + } + + private func configureLineViews() { + let requiredValues: [Any?] = [ + topView, bottomView, + topViewLeftConstraint, topViewRightConstraint, topViewTopConstraint, + bottomViewLeftConstraint, bottomViewRightConstraint, bottomViewBottomConstraint] + + if !requiredValues.contains(where: { $0 == nil }) { + return + } + + topView = createSeparatorView() + bottomView = createSeparatorView() + + configureConstrains() + } + + private func createSeparatorView() -> UIView { + let view = UIView() + view.isHidden = true + view.backgroundColor = .separatorColor + view.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(view) + return view + } + + private func configureConstrains() { + topView.heightAnchor.constraint(equalToConstant: .onePixelValue).isActive = true + bottomView.heightAnchor.constraint(equalToConstant: .onePixelValue).isActive = true + + // top separator + topViewTopConstraint = topView.topAnchor.constraint(equalTo: contentView.topAnchor) + topViewTopConstraint.isActive = true + + topViewRightConstraint = contentView.rightAnchor.constraint(equalTo: topView.rightAnchor) + topViewRightConstraint.isActive = true + + topViewLeftConstraint = topView.leftAnchor.constraint(equalTo: contentView.leftAnchor) + topViewLeftConstraint.isActive = true + + // bottom separator + bottomViewRightConstraint = contentView.rightAnchor.constraint(equalTo: bottomView.rightAnchor) + bottomViewRightConstraint.isActive = true + + bottomViewLeftConstraint = bottomView.leftAnchor.constraint(equalTo: contentView.leftAnchor) + bottomViewLeftConstraint.isActive = true + + bottomViewBottomConstraint = bottomView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) + bottomViewBottomConstraint.isActive = true + } + +} + +public extension TableRow where CellType.T: BaseCellViewModel { + + @discardableResult + func withSeparatorType(_ separatorType: CellSeparatorType) -> Self { + item.separatorType = separatorType + return self + } + +} diff --git a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift new file mode 100644 index 00000000..0051c497 --- /dev/null +++ b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift @@ -0,0 +1,89 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public struct SeparatorConfiguration { + let color: UIColor + let insets: UIEdgeInsets? +} + +public enum CellSeparatorType { + case none + case top(SeparatorConfiguration) + case bottom(SeparatorConfiguration) + + /// Top than bottom + case full(SeparatorConfiguration, SeparatorConfiguration) + + var bottomIsHidden: Bool { + switch self { + case .top(_), .none: + return true + default: + return false + } + } + + var topIsHidden: Bool { + switch self { + case .bottom(_), .none: + return true + default: + return false + } + } + +} + +/// By default this class does not provide any searators +open class BaseCellViewModel { + + var separatorType = CellSeparatorType.none + + /// NOTE: Bottom dimension is ignored + var topSeparatorConfiguration: SeparatorConfiguration? + + /// NOTE: Top dimension is ignored + var bottomSeparatorConfiguration: SeparatorConfiguration? + + @discardableResult + func with(separatorType: CellSeparatorType) -> Self { + self.separatorType = separatorType + + switch separatorType { + case .top(let configuration): + topSeparatorConfiguration = configuration + case .bottom(let configuration): + bottomSeparatorConfiguration = configuration + case .full(let top, let bottom): + topSeparatorConfiguration = top + bottomSeparatorConfiguration = bottom + default: + topSeparatorConfiguration = nil + bottomSeparatorConfiguration = nil + } + + return self + } + +} diff --git a/Sources/Classes/Views/BaseCell/EmptyCellRow.swift b/Sources/Classes/Views/BaseCell/EmptyCellRow.swift new file mode 100644 index 00000000..0ac14796 --- /dev/null +++ b/Sources/Classes/Views/BaseCell/EmptyCellRow.swift @@ -0,0 +1,50 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import TableKit + +/// Row that simulates spacing, can end editing on click, specify this in constructor +public final class EmptyCellRow: TableRow { + + convenience init(with height: CGFloat, + color: UIColor = .clear, + endEditingOnClick: Bool = false) { + + self.init(item: EmptyCellViewModel(height: height, color: color)) + + self.on(.click) { options in + if endEditingOnClick { + options.cell?.window?.endEditing(true) + } + } + } + + // Used for set custom height to each cell, not for each cell type + override var defaultHeight: CGFloat? { + return item.height + } + + var anyRow: AnyBaseTableRow { + return AnyBaseTableRow(tableRow: self) + } + +} From 6d16303908e4b3b302baa86e717454d1135c4ffe Mon Sep 17 00:00:00 2001 From: Igor Date: Sun, 8 Oct 2017 17:27:05 +0300 Subject: [PATCH 02/24] Add SeparatorConfiguration --- LeadKit.xcodeproj/project.pbxproj | 12 +++- Sources/Classes/Views/BaseCell/BaseCell.swift | 13 ++-- .../Views/BaseCell/BaseCellViewModel.swift | 33 ---------- .../Views/BaseCell/CellSeparatorType.swift | 60 +++++++++++++++++++ .../BaseCell/SeparatorConfiguration.swift | 37 ++++++++++++ 5 files changed, 115 insertions(+), 40 deletions(-) create mode 100644 Sources/Classes/Views/BaseCell/CellSeparatorType.swift create mode 100644 Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index b28bad93..7ac81361 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -400,6 +400,8 @@ A6E0DDEB1F8A6970002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; A6E0DDEC1F8A6970002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; A6E0DDED1F8A6970002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; + A6E0DDEF1F8A6C57002CA74E /* CellSeparatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */; }; + A6E0DDF11F8A6C80002CA74E /* SeparatorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */; }; A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */; }; A6F32C0A1F6EBE5B00AC08EE /* String+LocalizedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */; }; A6F32C0B1F6EBE5C00AC08EE /* String+LocalizedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */; }; @@ -596,6 +598,8 @@ A66428A61F8A653600C6308D /* BaseCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCell.swift; sourceTree = ""; }; A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = ""; }; A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyBaseTableRow.swift; sourceTree = ""; }; + A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSeparatorType.swift; sourceTree = ""; }; + A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorConfiguration.swift; sourceTree = ""; }; A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+LocalizedComponent.swift"; sourceTree = ""; }; A6F32C0E1F6EBE8E00AC08EE /* StringExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionTests.swift; sourceTree = ""; }; A854A36EB179651E6D0CC9FB /* Pods_LeadKit_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1246,10 +1250,12 @@ A66428A41F8A651700C6308D /* BaseCell */ = { isa = PBXGroup; children = ( - A66428A71F8A654600C6308D /* EmptyCellRow.swift */, + A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */, A66428A61F8A653600C6308D /* BaseCell.swift */, A66428A51F8A653500C6308D /* BaseCellViewModel.swift */, - A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */, + A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */, + A66428A71F8A654600C6308D /* EmptyCellRow.swift */, + A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */, ); path = BaseCell; sourceTree = ""; @@ -2042,6 +2048,7 @@ 671463201EB3396E00EAB194 /* Any+Cast.swift in Sources */, EFBE57DB1EC361620040E00A /* UIView+Layout.swift in Sources */, 6714639E1EB33AEB00EAB194 /* NetworkService+ActivityIndicator.swift in Sources */, + A6E0DDEF1F8A6C57002CA74E /* CellSeparatorType.swift in Sources */, 6714634C1EB3396E00EAB194 /* ReuseIdentifierProtocol.swift in Sources */, 671462F01EB3396E00EAB194 /* UIImage+SupportExtensions.swift in Sources */, 6771DFDE1EE99F6F002DCDAE /* DateFormattingArguments.swift in Sources */, @@ -2088,6 +2095,7 @@ EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671463701EB3396E00EAB194 /* ApiRequestParameters.swift in Sources */, 671462EC1EB3396E00EAB194 /* UIImage+Extensions.swift in Sources */, + A6E0DDF11F8A6C80002CA74E /* SeparatorConfiguration.swift in Sources */, 6714636C1EB3396E00EAB194 /* XibNameProtocol.swift in Sources */, 6771DFEA1EEA7CB8002DCDAE /* DateFormattingService+MappingTransform.swift in Sources */, 671462A41EB3396E00EAB194 /* IndexPath+ImmutableIndexPath.swift in Sources */, diff --git a/Sources/Classes/Views/BaseCell/BaseCell.swift b/Sources/Classes/Views/BaseCell/BaseCell.swift index 08ae1f97..c8fc0e4f 100644 --- a/Sources/Classes/Views/BaseCell/BaseCell.swift +++ b/Sources/Classes/Views/BaseCell/BaseCell.swift @@ -26,8 +26,9 @@ import TableKit open class BaseCell: UITableViewCell { func configureSeparator(with viewModel: BaseCellViewModel) { - topSeparatorInsets = viewModel.topSeparatorInsets ?? .zero - bottomSeparatorInsets = viewModel.bottomSeparatorInsets ?? .zero + topView + topSeparatorConfiguration = viewModel.topSeparatorInsets ?? .baseConfiguration + bottomSeparatorConfiguration = viewModel.bottomSeparatorInsets ?? .baseConfiguration } // MARK: - Private @@ -46,8 +47,8 @@ open class BaseCell: UITableViewCell { private var bottomViewBottomConstraint: NSLayoutConstraint! // insets - private var topSeparatorInsets: UIEdgeInsets = .zero - private var bottomSeparatorInsets: UIEdgeInsets = .zero + private var topSeparatorConfiguration = SeparatorConfiguration.baseConfiguration + private var bottomSeparatorConfiguration = SeparatorConfiguration.baseConfiguration override open func updateConstraints() { topViewTopConstraint.constant = topSeparatorInsets.top @@ -72,6 +73,8 @@ open class BaseCell: UITableViewCell { topView.isHidden = separatorType.topIsHidden bottomView.isHidden = separatorType.bottomIsHidden + topView.backgroundColor = + setNeedsUpdateConstraints() } @@ -94,7 +97,7 @@ open class BaseCell: UITableViewCell { private func createSeparatorView() -> UIView { let view = UIView() view.isHidden = true - view.backgroundColor = .separatorColor + view.backgroundColor = .black view.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(view) return view diff --git a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift index 0051c497..6b0981bb 100644 --- a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift +++ b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift @@ -22,39 +22,6 @@ import UIKit -public struct SeparatorConfiguration { - let color: UIColor - let insets: UIEdgeInsets? -} - -public enum CellSeparatorType { - case none - case top(SeparatorConfiguration) - case bottom(SeparatorConfiguration) - - /// Top than bottom - case full(SeparatorConfiguration, SeparatorConfiguration) - - var bottomIsHidden: Bool { - switch self { - case .top(_), .none: - return true - default: - return false - } - } - - var topIsHidden: Bool { - switch self { - case .bottom(_), .none: - return true - default: - return false - } - } - -} - /// By default this class does not provide any searators open class BaseCellViewModel { diff --git a/Sources/Classes/Views/BaseCell/CellSeparatorType.swift b/Sources/Classes/Views/BaseCell/CellSeparatorType.swift new file mode 100644 index 00000000..f6de41c6 --- /dev/null +++ b/Sources/Classes/Views/BaseCell/CellSeparatorType.swift @@ -0,0 +1,60 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public enum CellSeparatorType { + case none + case top(SeparatorConfiguration) + case bottom(SeparatorConfiguration) + + /// Top than bottom + case full(SeparatorConfiguration, SeparatorConfiguration) + + var bottomIsHidden: Bool { + switch self { + case .top, .none: + return true + default: + return false + } + } + + var topIsHidden: Bool { + switch self { + case .bottom, .none: + return true + default: + return false + } + } + + var topConfiguration: SeparatorConfiguration? { + switch self { + case .top(let configuration), .full(let configuration, _): + return configuration + default: + return nil + } + } + +} diff --git a/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift b/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift new file mode 100644 index 00000000..077861dd --- /dev/null +++ b/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift @@ -0,0 +1,37 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public struct SeparatorConfiguration { + let color: UIColor + let insets: UIEdgeInsets? + let height: CGFloat + + init(color: UIColor, insets: UIEdgeInsets? = .zero, height: CGFloat = CGFloat(pixels: 1)) { + self.color = color + self.insets = insets + self.height = height + } + + static let baseConfiguration = SeparatorConfiguration(color: .black, insets: .zero) +} From a7f324dd793f28b21a14ac3fd0785cad594031a5 Mon Sep 17 00:00:00 2001 From: Igor Date: Sun, 8 Oct 2017 20:09:36 +0300 Subject: [PATCH 03/24] Add comparable --- LeadKit.xcodeproj/project.pbxproj | 12 ++++++++++++ .../Comparable/Comparable+Extensions.swift | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 Sources/Extensions/Comparable/Comparable+Extensions.swift diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index 7ac81361..e5da7011 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -384,6 +384,7 @@ 67E6C2371EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 67E6C2381EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; }; + A6D10EAB1F8A9278003E69DD /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; A6E0DDDF1F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; A6E0DDE01F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; @@ -598,6 +599,7 @@ A66428A61F8A653600C6308D /* BaseCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCell.swift; sourceTree = ""; }; A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = ""; }; A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyBaseTableRow.swift; sourceTree = ""; }; + A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Comparable+Extensions.swift"; sourceTree = ""; }; A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSeparatorType.swift; sourceTree = ""; }; A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorConfiguration.swift; sourceTree = ""; }; A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+LocalizedComponent.swift"; sourceTree = ""; }; @@ -762,6 +764,7 @@ 671461DA1EB3396E00EAB194 /* Extensions */ = { isa = PBXGroup; children = ( + A6D10EA91F8A9269003E69DD /* Comparable */, 671461DB1EB3396E00EAB194 /* Alamofire */, EFBE57CE1EC35ED90040E00A /* Array */, 67A1FF921EBCA64A00D6C89F /* CABasicAnimation */, @@ -1260,6 +1263,14 @@ path = BaseCell; sourceTree = ""; }; + A6D10EA91F8A9269003E69DD /* Comparable */ = { + isa = PBXGroup; + children = ( + A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */, + ); + path = Comparable; + sourceTree = ""; + }; A6F32C0D1F6EBE7700AC08EE /* Extensions */ = { isa = PBXGroup; children = ( @@ -2076,6 +2087,7 @@ 6714624C1EB3396E00EAB194 /* MapCursor.swift in Sources */, 671463241EB3396E00EAB194 /* Any+TypeName.swift in Sources */, 671463881EB3396E00EAB194 /* RoundDrawingOperation.swift in Sources */, + A6D10EAB1F8A9278003E69DD /* Comparable+Extensions.swift in Sources */, 671463801EB3396E00EAB194 /* PaddingDrawingOperation.swift in Sources */, 671462E01EB3396E00EAB194 /* UICollectionView+CellRegistration.swift in Sources */, 671462601EB3396E00EAB194 /* PaginationTableViewWrapper.swift in Sources */, diff --git a/Sources/Extensions/Comparable/Comparable+Extensions.swift b/Sources/Extensions/Comparable/Comparable+Extensions.swift new file mode 100644 index 00000000..97886d82 --- /dev/null +++ b/Sources/Extensions/Comparable/Comparable+Extensions.swift @@ -0,0 +1,17 @@ +// +// Comparable+Extensions.swift +// LeadKit iOS +// +// Created by Igor Kislyuk on 08/10/2017. +// Copyright © 2017 Touch Instinct. All rights reserved. +// + +import Foundation + +extension Comparable { + + func `in`(bounds: (lower: Self, upper: Self)) -> Self { + return min(max(bounds.lower, self), bounds.upper) + } + +} From 0ef07e8bc6a3f942c54cf053db4fd71f1c1f2769 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 17:29:48 +0300 Subject: [PATCH 04/24] Fix building for cells --- LeadKit.xcodeproj/project.pbxproj | 60 +++++++++++++++++-- .../AnyBaseTableRow.swift | 0 Sources/Classes/Views/BaseCell/BaseCell.swift | 41 +++++++------ .../Views/BaseCell/BaseCellViewModel.swift | 12 ++-- .../Views/BaseCell/CellSeparatorType.swift | 6 +- .../BaseCell/SeparatorConfiguration.swift | 4 +- .../Classes/Views/EmptyCell/EmptyCell.swift | 49 +++++++++++++++ .../EmptyCellRow.swift | 15 ++--- .../Views/EmptyCell/EmptyCellViewModel.swift | 34 +++++++++++ .../Views/{ => SpinnerView}/SpinnerView.swift | 0 .../Classes/Views/{ => XibView}/XibView.swift | 0 .../Comparable/Comparable+Extensions.swift | 22 +++++-- 12 files changed, 200 insertions(+), 43 deletions(-) rename Sources/Classes/Views/{BaseCell => AnyBaseTableRow}/AnyBaseTableRow.swift (100%) create mode 100644 Sources/Classes/Views/EmptyCell/EmptyCell.swift rename Sources/Classes/Views/{BaseCell => EmptyCell}/EmptyCellRow.swift (80%) create mode 100644 Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift rename Sources/Classes/Views/{ => SpinnerView}/SpinnerView.swift (100%) rename Sources/Classes/Views/{ => XibView}/XibView.swift (100%) diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index e5da7011..325c2e0d 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -384,6 +384,14 @@ 67E6C2371EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 67E6C2381EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; }; + A6C9A4FA1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; + A6C9A4FB1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; + A6C9A4FC1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; + A6C9A4FD1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; + A6C9A4FE1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; + A6C9A4FF1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; + A6C9A5001F8BBCF3009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; + A6C9A5011F8BBCF3009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; A6D10EAB1F8A9278003E69DD /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; A6E0DDDF1F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; @@ -599,6 +607,8 @@ A66428A61F8A653600C6308D /* BaseCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCell.swift; sourceTree = ""; }; A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = ""; }; A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyBaseTableRow.swift; sourceTree = ""; }; + A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellViewModel.swift; sourceTree = ""; }; + A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCell.swift; sourceTree = ""; }; A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Comparable+Extensions.swift"; sourceTree = ""; }; A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSeparatorType.swift; sourceTree = ""; }; A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorConfiguration.swift; sourceTree = ""; }; @@ -744,9 +754,11 @@ 671461D41EB3396E00EAB194 /* Views */ = { isa = PBXGroup; children = ( + A6AF3B381F8B957400CDB971 /* AnyBaseTableRow */, A66428A41F8A651700C6308D /* BaseCell */, - 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */, - 671461D51EB3396E00EAB194 /* XibView.swift */, + A6C9A4F71F8BBC0F009311CC /* EmptyCell */, + A6C9A4F81F8BBC27009311CC /* SpinnerView */, + A6C9A4F91F8BBCCE009311CC /* XibView */, ); path = Views; sourceTree = ""; @@ -1253,16 +1265,48 @@ A66428A41F8A651700C6308D /* BaseCell */ = { isa = PBXGroup; children = ( - A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */, A66428A61F8A653600C6308D /* BaseCell.swift */, A66428A51F8A653500C6308D /* BaseCellViewModel.swift */, A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */, - A66428A71F8A654600C6308D /* EmptyCellRow.swift */, A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */, ); path = BaseCell; sourceTree = ""; }; + A6AF3B381F8B957400CDB971 /* AnyBaseTableRow */ = { + isa = PBXGroup; + children = ( + A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */, + ); + path = AnyBaseTableRow; + sourceTree = ""; + }; + A6C9A4F71F8BBC0F009311CC /* EmptyCell */ = { + isa = PBXGroup; + children = ( + A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */, + A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */, + A66428A71F8A654600C6308D /* EmptyCellRow.swift */, + ); + path = EmptyCell; + sourceTree = ""; + }; + A6C9A4F81F8BBC27009311CC /* SpinnerView */ = { + isa = PBXGroup; + children = ( + 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */, + ); + path = SpinnerView; + sourceTree = ""; + }; + A6C9A4F91F8BBCCE009311CC /* XibView */ = { + isa = PBXGroup; + children = ( + 671461D51EB3396E00EAB194 /* XibView.swift */, + ); + path = XibView; + sourceTree = ""; + }; A6D10EA91F8A9269003E69DD /* Comparable */ = { isa = PBXGroup; children = ( @@ -2085,6 +2129,7 @@ 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */, 671463301EB3396E00EAB194 /* CursorType.swift in Sources */, 6714624C1EB3396E00EAB194 /* MapCursor.swift in Sources */, + A6C9A4FA1F8BBCF2009311CC /* EmptyCell.swift in Sources */, 671463241EB3396E00EAB194 /* Any+TypeName.swift in Sources */, 671463881EB3396E00EAB194 /* RoundDrawingOperation.swift in Sources */, A6D10EAB1F8A9278003E69DD /* Comparable+Extensions.swift in Sources */, @@ -2103,6 +2148,7 @@ 671462781EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, A6E0DDE11F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */, A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */, + A6C9A4FB1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */, 671463041EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671463701EB3396E00EAB194 /* ApiRequestParameters.swift in Sources */, @@ -2168,7 +2214,9 @@ A6E0DDE41F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, 671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */, A6F32C101F6EBE9600AC08EE /* StringExtensionTests.swift in Sources */, + A6C9A4FC1F8BBCF2009311CC /* EmptyCell.swift in Sources */, 671463C11EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, + A6C9A4FD1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */, 671463BE1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */, A6E0DDE21F8A696F002CA74E /* EmptyCellRow.swift in Sources */, A6E0DDE31F8A696F002CA74E /* BaseCell.swift in Sources */, @@ -2404,6 +2452,7 @@ 671462991EB3396E00EAB194 /* CGSize+Resize.swift in Sources */, 671462F91EB3396E00EAB194 /* UIView+DefaultReuseIdentifier.swift in Sources */, 671463591EB3396E00EAB194 /* StoryboardIdentifierProtocol.swift in Sources */, + A6C9A4FF1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */, 671463311EB3396E00EAB194 /* CursorType.swift in Sources */, 6714624D1EB3396E00EAB194 /* MapCursor.swift in Sources */, 671463251EB3396E00EAB194 /* Any+TypeName.swift in Sources */, @@ -2449,6 +2498,7 @@ 671462C91EB3396E00EAB194 /* String+Localization.swift in Sources */, 671462B91EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */, 671463751EB3396E00EAB194 /* BorderDrawingOperation.swift in Sources */, + A6C9A4FE1F8BBCF2009311CC /* EmptyCell.swift in Sources */, 6714633D1EB3396E00EAB194 /* LoadingIndicator.swift in Sources */, 671463191EB3396E00EAB194 /* UIWindow+Extensions.swift in Sources */, EFBE57DC1EC361620040E00A /* UIView+Layout.swift in Sources */, @@ -2486,7 +2536,9 @@ A6E0DDEC1F8A6970002CA74E /* BaseCellViewModel.swift in Sources */, 671463CB1EB34B1E00EAB194 /* TestView.swift in Sources */, A6F32C111F6EBE9700AC08EE /* StringExtensionTests.swift in Sources */, + A6C9A5001F8BBCF3009311CC /* EmptyCell.swift in Sources */, 671463C81EB34B1E00EAB194 /* PaginationViewModelTests.swift in Sources */, + A6C9A5011F8BBCF3009311CC /* EmptyCellViewModel.swift in Sources */, 671463BC1EB34B1E00EAB194 /* CursorTests.swift in Sources */, A6E0DDEA1F8A6970002CA74E /* EmptyCellRow.swift in Sources */, A6E0DDEB1F8A6970002CA74E /* BaseCell.swift in Sources */, diff --git a/Sources/Classes/Views/BaseCell/AnyBaseTableRow.swift b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift similarity index 100% rename from Sources/Classes/Views/BaseCell/AnyBaseTableRow.swift rename to Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift diff --git a/Sources/Classes/Views/BaseCell/BaseCell.swift b/Sources/Classes/Views/BaseCell/BaseCell.swift index c8fc0e4f..f9424f0b 100644 --- a/Sources/Classes/Views/BaseCell/BaseCell.swift +++ b/Sources/Classes/Views/BaseCell/BaseCell.swift @@ -25,10 +25,17 @@ import TableKit open class BaseCell: UITableViewCell { - func configureSeparator(with viewModel: BaseCellViewModel) { - topView - topSeparatorConfiguration = viewModel.topSeparatorInsets ?? .baseConfiguration - bottomSeparatorConfiguration = viewModel.bottomSeparatorInsets ?? .baseConfiguration + public func configureSeparator(with viewModel: BaseCellViewModel) { + topView.isHidden = viewModel.separatorType.topIsHidden + bottomView.isHidden = viewModel.separatorType.bottomIsHidden + + topView.backgroundColor = viewModel.topSeparatorConfiguration?.color + topViewHeightConstraint.constant = viewModel.topSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + topSeparatorInsets = viewModel.topSeparatorConfiguration?.insets ?? .zero + + bottomView.backgroundColor = viewModel.bottomSeparatorConfiguration?.color + bottomViewHeightConstraint.constant = viewModel.bottomSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + bottomSeparatorInsets = viewModel.bottomSeparatorConfiguration?.insets ?? .zero } // MARK: - Private @@ -41,14 +48,18 @@ open class BaseCell: UITableViewCell { private var topViewRightConstraint: NSLayoutConstraint! private var topViewTopConstraint: NSLayoutConstraint! + private var topViewHeightConstraint: NSLayoutConstraint! + // bottom separator private var bottomViewLeftConstraint: NSLayoutConstraint! private var bottomViewRightConstraint: NSLayoutConstraint! private var bottomViewBottomConstraint: NSLayoutConstraint! + private var bottomViewHeightConstraint: NSLayoutConstraint! + // insets - private var topSeparatorConfiguration = SeparatorConfiguration.baseConfiguration - private var bottomSeparatorConfiguration = SeparatorConfiguration.baseConfiguration + private var topSeparatorInsets = UIEdgeInsets.zero + private var bottomSeparatorInsets = UIEdgeInsets.zero override open func updateConstraints() { topViewTopConstraint.constant = topSeparatorInsets.top @@ -66,16 +77,6 @@ open class BaseCell: UITableViewCell { super.awakeFromNib() configureLineViews() - configureSeparator(with: .none) - } - - private func configureSeparator(with separatorType: CellSeparatorType) { - topView.isHidden = separatorType.topIsHidden - bottomView.isHidden = separatorType.bottomIsHidden - - topView.backgroundColor = - - setNeedsUpdateConstraints() } private func configureLineViews() { @@ -104,8 +105,12 @@ open class BaseCell: UITableViewCell { } private func configureConstrains() { - topView.heightAnchor.constraint(equalToConstant: .onePixelValue).isActive = true - bottomView.heightAnchor.constraint(equalToConstant: .onePixelValue).isActive = true + // height + topViewHeightConstraint = topView.heightAnchor.constraint(equalToConstant: CGFloat(pixels: 1)) + topViewHeightConstraint.isActive = true + + bottomViewHeightConstraint = bottomView.heightAnchor.constraint(equalToConstant: CGFloat(pixels: 1)) + bottomViewHeightConstraint.isActive = true // top separator topViewTopConstraint = topView.topAnchor.constraint(equalTo: contentView.topAnchor) diff --git a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift index 6b0981bb..82725c2e 100644 --- a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift +++ b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift @@ -22,7 +22,7 @@ import UIKit -/// By default this class does not provide any searators +/// By default this class does not provide any separators open class BaseCellViewModel { var separatorType = CellSeparatorType.none @@ -34,19 +34,21 @@ open class BaseCellViewModel { var bottomSeparatorConfiguration: SeparatorConfiguration? @discardableResult - func with(separatorType: CellSeparatorType) -> Self { + public func with(separatorType: CellSeparatorType) -> Self { self.separatorType = separatorType switch separatorType { case .top(let configuration): - topSeparatorConfiguration = configuration + topSeparatorConfiguration = configuration + bottomSeparatorConfiguration = nil case .bottom(let configuration): + topSeparatorConfiguration = nil bottomSeparatorConfiguration = configuration case .full(let top, let bottom): - topSeparatorConfiguration = top + topSeparatorConfiguration = top bottomSeparatorConfiguration = bottom default: - topSeparatorConfiguration = nil + topSeparatorConfiguration = nil bottomSeparatorConfiguration = nil } diff --git a/Sources/Classes/Views/BaseCell/CellSeparatorType.swift b/Sources/Classes/Views/BaseCell/CellSeparatorType.swift index f6de41c6..df251706 100644 --- a/Sources/Classes/Views/BaseCell/CellSeparatorType.swift +++ b/Sources/Classes/Views/BaseCell/CellSeparatorType.swift @@ -30,7 +30,7 @@ public enum CellSeparatorType { /// Top than bottom case full(SeparatorConfiguration, SeparatorConfiguration) - var bottomIsHidden: Bool { + public var bottomIsHidden: Bool { switch self { case .top, .none: return true @@ -39,7 +39,7 @@ public enum CellSeparatorType { } } - var topIsHidden: Bool { + public var topIsHidden: Bool { switch self { case .bottom, .none: return true @@ -48,7 +48,7 @@ public enum CellSeparatorType { } } - var topConfiguration: SeparatorConfiguration? { + public var topConfiguration: SeparatorConfiguration? { switch self { case .top(let configuration), .full(let configuration, _): return configuration diff --git a/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift b/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift index 077861dd..0af8a3c2 100644 --- a/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift +++ b/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift @@ -27,11 +27,11 @@ public struct SeparatorConfiguration { let insets: UIEdgeInsets? let height: CGFloat - init(color: UIColor, insets: UIEdgeInsets? = .zero, height: CGFloat = CGFloat(pixels: 1)) { + public init(color: UIColor, insets: UIEdgeInsets? = .zero, height: CGFloat = CGFloat(pixels: 1)) { self.color = color self.insets = insets self.height = height } - static let baseConfiguration = SeparatorConfiguration(color: .black, insets: .zero) + public static let baseConfiguration = SeparatorConfiguration(color: .black, insets: .zero) } diff --git a/Sources/Classes/Views/EmptyCell/EmptyCell.swift b/Sources/Classes/Views/EmptyCell/EmptyCell.swift new file mode 100644 index 00000000..6a759c2d --- /dev/null +++ b/Sources/Classes/Views/EmptyCell/EmptyCell.swift @@ -0,0 +1,49 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit +import TableKit + +public final class EmptyCell: BaseCell, ConfigurableCell { + + private weak var coloredView: UIView! + + override public func awakeFromNib() { + super.awakeFromNib() + + let view = UIView() + addSubview(view) + + topAnchor.constraint(equalTo: view.topAnchor).isActive = true + bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true + leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true + trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true + + coloredView = view + } + + public func configure(with viewModel: EmptyCellViewModel) { + configureSeparator(with: viewModel) + coloredView.backgroundColor = viewModel.color + } + +} diff --git a/Sources/Classes/Views/BaseCell/EmptyCellRow.swift b/Sources/Classes/Views/EmptyCell/EmptyCellRow.swift similarity index 80% rename from Sources/Classes/Views/BaseCell/EmptyCellRow.swift rename to Sources/Classes/Views/EmptyCell/EmptyCellRow.swift index 0ac14796..b0a64a95 100644 --- a/Sources/Classes/Views/BaseCell/EmptyCellRow.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCellRow.swift @@ -25,25 +25,26 @@ import TableKit /// Row that simulates spacing, can end editing on click, specify this in constructor public final class EmptyCellRow: TableRow { - convenience init(with height: CGFloat, - color: UIColor = .clear, - endEditingOnClick: Bool = false) { + public convenience init(with height: CGFloat, + color: UIColor = .clear, + endEditingOnClick: Bool = false) { self.init(item: EmptyCellViewModel(height: height, color: color)) - self.on(.click) { options in - if endEditingOnClick { + if endEditingOnClick { + self.on(.click) { options in options.cell?.window?.endEditing(true) } } } // Used for set custom height to each cell, not for each cell type - override var defaultHeight: CGFloat? { + override public var defaultHeight: CGFloat? { return item.height } - var anyRow: AnyBaseTableRow { + /// - returns: EmptyCellRow typed as AnyBaseTableRow + public var anyRow: AnyBaseTableRow { return AnyBaseTableRow(tableRow: self) } diff --git a/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift b/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift new file mode 100644 index 00000000..6508837f --- /dev/null +++ b/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift @@ -0,0 +1,34 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import UIKit + +public final class EmptyCellViewModel: BaseCellViewModel { + + let color: UIColor + let height: CGFloat + + public init(height: CGFloat, color: UIColor = .clear) { + self.color = color + self.height = height + } +} diff --git a/Sources/Classes/Views/SpinnerView.swift b/Sources/Classes/Views/SpinnerView/SpinnerView.swift similarity index 100% rename from Sources/Classes/Views/SpinnerView.swift rename to Sources/Classes/Views/SpinnerView/SpinnerView.swift diff --git a/Sources/Classes/Views/XibView.swift b/Sources/Classes/Views/XibView/XibView.swift similarity index 100% rename from Sources/Classes/Views/XibView.swift rename to Sources/Classes/Views/XibView/XibView.swift diff --git a/Sources/Extensions/Comparable/Comparable+Extensions.swift b/Sources/Extensions/Comparable/Comparable+Extensions.swift index 97886d82..ed43e9c6 100644 --- a/Sources/Extensions/Comparable/Comparable+Extensions.swift +++ b/Sources/Extensions/Comparable/Comparable+Extensions.swift @@ -1,9 +1,23 @@ // -// Comparable+Extensions.swift -// LeadKit iOS +// Copyright (c) 2017 Touch Instinct // -// Created by Igor Kislyuk on 08/10/2017. -// Copyright © 2017 Touch Instinct. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import Foundation From 1051033913eae278025af5450dca3935ace63a78 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 17:31:53 +0300 Subject: [PATCH 05/24] Bump version and changelog --- CHANGELOG.md | 6 +++++- LeadKit.podspec | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5683a58..e85c587d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,4 +18,8 @@ ## 0.5.10 -- **Fix**: `Public` modifier for `SpinnerView` \ No newline at end of file +- **Fix**: `Public` modifier for `SpinnerView` + +## 0.5.11 + +- **Add**: `BaseCell`, `AnyBaseTableRow`, `EmptyCell`, `EmptyCellRow` \ No newline at end of file diff --git a/LeadKit.podspec b/LeadKit.podspec index dba0d228..fe19f2d9 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LeadKit" - s.version = "0.5.10" + s.version = "0.5.11" s.summary = "iOS framework with a bunch of tools for rapid development" s.homepage = "https://github.com/TouchInstinct/LeadKit" s.license = "Apache License, Version 2.0" From 8d578e7f2333ef25bd31300ab28300db579282c2 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 17:56:18 +0300 Subject: [PATCH 06/24] Fix podspec --- LeadKit.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LeadKit.podspec b/LeadKit.podspec index fe19f2d9..c6263e09 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -41,8 +41,7 @@ Pod::Spec.new do |s| ss.source_files = "Sources/**/*.swift" ss.watchos.exclude_files = [ "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", - "Sources/Classes/Views/XibView.swift", - "Sources/Classes/Views/SpinnerView.swift", + "Sources/Classes/Views/*", "Sources/Extensions/CABasicAnimation/*", "Sources/Extensions/CGFloat/CGFloat+Pixels.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", @@ -92,6 +91,7 @@ Pod::Spec.new do |s| ss.source_files = "Sources/**/*.swift" ss.exclude_files = [ + "Sources/Classes/Views/*", "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", From 08dbf13d7b2d927f929893f24f637aa43499254f Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 18:05:52 +0300 Subject: [PATCH 07/24] Fix target dependencies --- LeadKit.xcodeproj/project.pbxproj | 46 +++++++------------ .../Comparable/Comparable+Extensions.swift | 2 +- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index 325c2e0d..8d6d6e61 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -386,29 +386,22 @@ 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; }; A6C9A4FA1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; A6C9A4FB1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; - A6C9A4FC1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; - A6C9A4FD1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; - A6C9A4FE1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; - A6C9A4FF1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; - A6C9A5001F8BBCF3009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; - A6C9A5011F8BBCF3009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; + A6C9A5041F8BC78F009311CC /* CellSeparatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */; }; + A6C9A5051F8BC78F009311CC /* SeparatorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */; }; + A6C9A50C1F8BC799009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; + A6C9A50D1F8BC799009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; + A6C9A50E1F8BC799009311CC /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; + A6C9A50F1F8BC79D009311CC /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; + A6C9A5101F8BC79D009311CC /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; + A6C9A5111F8BC79D009311CC /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; A6D10EAB1F8A9278003E69DD /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; A6E0DDDF1F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; A6E0DDE01F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; A6E0DDE11F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; - A6E0DDE21F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; A6E0DDE31F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; A6E0DDE41F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; A6E0DDE51F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; - A6E0DDE61F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; - A6E0DDE71F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; - A6E0DDE81F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; - A6E0DDE91F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; - A6E0DDEA1F8A6970002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; - A6E0DDEB1F8A6970002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; - A6E0DDEC1F8A6970002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; - A6E0DDED1F8A6970002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; A6E0DDEF1F8A6C57002CA74E /* CellSeparatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */; }; A6E0DDF11F8A6C80002CA74E /* SeparatorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */; }; A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */; }; @@ -2208,20 +2201,23 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A6C9A5051F8BC78F009311CC /* SeparatorConfiguration.swift in Sources */, + A6C9A50D1F8BC799009311CC /* EmptyCellViewModel.swift in Sources */, 671463CA1EB34B1E00EAB194 /* TestView.swift in Sources */, 671463C71EB34B1E00EAB194 /* PaginationViewModelTests.swift in Sources */, + A6C9A50E1F8BC799009311CC /* EmptyCellRow.swift in Sources */, + A6C9A50C1F8BC799009311CC /* EmptyCell.swift in Sources */, 671463B81EB34B1E00EAB194 /* StubCursor.swift in Sources */, A6E0DDE41F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, 671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */, A6F32C101F6EBE9600AC08EE /* StringExtensionTests.swift in Sources */, - A6C9A4FC1F8BBCF2009311CC /* EmptyCell.swift in Sources */, 671463C11EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, - A6C9A4FD1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */, 671463BE1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */, - A6E0DDE21F8A696F002CA74E /* EmptyCellRow.swift in Sources */, A6E0DDE31F8A696F002CA74E /* BaseCell.swift in Sources */, + A6C9A50F1F8BC79D009311CC /* Comparable+Extensions.swift in Sources */, 671463C41EB34B1E00EAB194 /* Post.swift in Sources */, A6E0DDE51F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */, + A6C9A5041F8BC78F009311CC /* CellSeparatorType.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2420,7 +2416,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A6E0DDE61F8A696F002CA74E /* EmptyCellRow.swift in Sources */, 671463491EB3396E00EAB194 /* ResettableType.swift in Sources */, 671462E51EB3396E00EAB194 /* UIColor+Hex.swift in Sources */, 671462CD1EB3396E00EAB194 /* String+SizeCalculation.swift in Sources */, @@ -2452,7 +2447,6 @@ 671462991EB3396E00EAB194 /* CGSize+Resize.swift in Sources */, 671462F91EB3396E00EAB194 /* UIView+DefaultReuseIdentifier.swift in Sources */, 671463591EB3396E00EAB194 /* StoryboardIdentifierProtocol.swift in Sources */, - A6C9A4FF1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */, 671463311EB3396E00EAB194 /* CursorType.swift in Sources */, 6714624D1EB3396E00EAB194 /* MapCursor.swift in Sources */, 671463251EB3396E00EAB194 /* Any+TypeName.swift in Sources */, @@ -2461,12 +2455,10 @@ 671462E11EB3396E00EAB194 /* UICollectionView+CellRegistration.swift in Sources */, A6F32C0A1F6EBE5B00AC08EE /* String+LocalizedComponent.swift in Sources */, 671463291EB3396E00EAB194 /* BaseViewModel.swift in Sources */, - A6E0DDE71F8A696F002CA74E /* BaseCell.swift in Sources */, 671462AD1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */, 671463011EB3396E00EAB194 /* UIView+LoadFromNib.swift in Sources */, 6714627D1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */, 671463451EB3396E00EAB194 /* ObservableMappable.swift in Sources */, - A6E0DDE91F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */, 671462591EB3396E00EAB194 /* Log.swift in Sources */, 671462791EB3396E00EAB194 /* ResizeContentMode.swift in Sources */, 671463051EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, @@ -2493,12 +2485,12 @@ 6771DFD91EE99EBA002DCDAE /* DateFormattingService.swift in Sources */, 671462951EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */, 671463651EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */, + A6C9A5101F8BC79D009311CC /* Comparable+Extensions.swift in Sources */, 671462491EB3396E00EAB194 /* FixedPageCursor.swift in Sources */, EFBE57E11EC362470040E00A /* AlertRepresentable.swift in Sources */, 671462C91EB3396E00EAB194 /* String+Localization.swift in Sources */, 671462B91EB3396E00EAB194 /* Sequence+ConcurrentMap.swift in Sources */, 671463751EB3396E00EAB194 /* BorderDrawingOperation.swift in Sources */, - A6C9A4FE1F8BBCF2009311CC /* EmptyCell.swift in Sources */, 6714633D1EB3396E00EAB194 /* LoadingIndicator.swift in Sources */, 671463191EB3396E00EAB194 /* UIWindow+Extensions.swift in Sources */, EFBE57DC1EC361620040E00A /* UIView+Layout.swift in Sources */, @@ -2512,7 +2504,6 @@ 6714628D1EB3396E00EAB194 /* CGImage+Alpha.swift in Sources */, 671462751EB3396E00EAB194 /* LeadKitError.swift in Sources */, EFBE57D11EC35EF20040E00A /* Array+Extensions.swift in Sources */, - A6E0DDE81F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, 67CDEE431EB3AD1C00895905 /* NetworkService+RxLoadImage.swift in Sources */, 671462D91EB3396E00EAB194 /* TimeInterval+DateComponents.swift in Sources */, 6714638D1EB3396E00EAB194 /* SolidFillDrawingOperation.swift in Sources */, @@ -2531,19 +2522,14 @@ buildActionMask = 2147483647; files = ( 671463C21EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, + A6C9A5111F8BC79D009311CC /* Comparable+Extensions.swift in Sources */, 671463BF1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */, 671463C51EB34B1E00EAB194 /* Post.swift in Sources */, - A6E0DDEC1F8A6970002CA74E /* BaseCellViewModel.swift in Sources */, 671463CB1EB34B1E00EAB194 /* TestView.swift in Sources */, A6F32C111F6EBE9700AC08EE /* StringExtensionTests.swift in Sources */, - A6C9A5001F8BBCF3009311CC /* EmptyCell.swift in Sources */, 671463C81EB34B1E00EAB194 /* PaginationViewModelTests.swift in Sources */, - A6C9A5011F8BBCF3009311CC /* EmptyCellViewModel.swift in Sources */, 671463BC1EB34B1E00EAB194 /* CursorTests.swift in Sources */, - A6E0DDEA1F8A6970002CA74E /* EmptyCellRow.swift in Sources */, - A6E0DDEB1F8A6970002CA74E /* BaseCell.swift in Sources */, 671463B91EB34B1E00EAB194 /* StubCursor.swift in Sources */, - A6E0DDED1F8A6970002CA74E /* AnyBaseTableRow.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/Extensions/Comparable/Comparable+Extensions.swift b/Sources/Extensions/Comparable/Comparable+Extensions.swift index ed43e9c6..9589de93 100644 --- a/Sources/Extensions/Comparable/Comparable+Extensions.swift +++ b/Sources/Extensions/Comparable/Comparable+Extensions.swift @@ -22,7 +22,7 @@ import Foundation -extension Comparable { +public extension Comparable { func `in`(bounds: (lower: Self, upper: Self)) -> Self { return min(max(bounds.lower, self), bounds.upper) From bc746eafb99a8544d99e84a7c12f7d75d16bd534 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 18:07:27 +0300 Subject: [PATCH 08/24] Fix podspec --- LeadKit.podspec | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LeadKit.podspec b/LeadKit.podspec index c6263e09..2f4dc960 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -91,7 +91,9 @@ Pod::Spec.new do |s| ss.source_files = "Sources/**/*.swift" ss.exclude_files = [ - "Sources/Classes/Views/*", + "Sources/Classes/Views/AnyBaseTableRow/*", + "Sources/Classes/Views/BaseCell/*", + "Sources/Classes/Views/EmptyCell/*", "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", From 8a9a0cca4aef422c4ed1a08c2a1194a9d15d2518 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 18:14:24 +0300 Subject: [PATCH 09/24] Update podspec --- LeadKit.podspec | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/LeadKit.podspec b/LeadKit.podspec index 2f4dc960..19c6ce34 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -41,7 +41,7 @@ Pod::Spec.new do |s| ss.source_files = "Sources/**/*.swift" ss.watchos.exclude_files = [ "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", - "Sources/Classes/Views/*", + "Sources/Classes/Views/**/*.swift", "Sources/Extensions/CABasicAnimation/*", "Sources/Extensions/CGFloat/CGFloat+Pixels.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", @@ -91,9 +91,7 @@ Pod::Spec.new do |s| ss.source_files = "Sources/**/*.swift" ss.exclude_files = [ - "Sources/Classes/Views/AnyBaseTableRow/*", - "Sources/Classes/Views/BaseCell/*", - "Sources/Classes/Views/EmptyCell/*", + "Sources/Classes/Views/**/*.swift", "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", From 5ace1632233be6b8fb58435cd009e53d58f0e3a3 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 18:44:56 +0300 Subject: [PATCH 10/24] Fix podspec --- LeadKit.podspec | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/LeadKit.podspec b/LeadKit.podspec index 19c6ce34..586ef82f 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -41,7 +41,11 @@ Pod::Spec.new do |s| ss.source_files = "Sources/**/*.swift" ss.watchos.exclude_files = [ "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", - "Sources/Classes/Views/**/*.swift", + "Sources/Classes/Views/AnyBaseTableRow/*", + "Sources/Classes/Views/BaseCell/*", + "Sources/Classes/Views/EmptyCell/*", + "Sources/Classes/Views/XibView/*", + "Sources/Classes/Views/SpinnerView/*", "Sources/Extensions/CABasicAnimation/*", "Sources/Extensions/CGFloat/CGFloat+Pixels.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", @@ -67,6 +71,9 @@ Pod::Spec.new do |s| "Sources/Structures/DrawingOperations/BorderDrawingOperation.swift", ] ss.tvos.exclude_files = [ + "Sources/Classes/Views/AnyBaseTableRow/*", + "Sources/Classes/Views/BaseCell/*", + "Sources/Classes/Views/EmptyCell/*", "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Structures/Drawing/CALayerDrawingOperation.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", @@ -91,7 +98,9 @@ Pod::Spec.new do |s| ss.source_files = "Sources/**/*.swift" ss.exclude_files = [ - "Sources/Classes/Views/**/*.swift", + "Sources/Classes/Views/AnyBaseTableRow/*", + "Sources/Classes/Views/BaseCell/*", + "Sources/Classes/Views/EmptyCell/*", "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", From ab6af95df3309835a05eb330834e413eff493946 Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 19:36:04 +0300 Subject: [PATCH 11/24] Fix init --- Sources/Classes/Views/BaseCell/BaseCellViewModel.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift index 82725c2e..5306b8ee 100644 --- a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift +++ b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift @@ -33,6 +33,8 @@ open class BaseCellViewModel { /// NOTE: Top dimension is ignored var bottomSeparatorConfiguration: SeparatorConfiguration? + public init() {} + @discardableResult public func with(separatorType: CellSeparatorType) -> Self { self.separatorType = separatorType From b7d639a3c8adace4ad3bff045b795bc3f358788d Mon Sep 17 00:00:00 2001 From: Igor Date: Mon, 9 Oct 2017 20:30:48 +0300 Subject: [PATCH 12/24] Fix bug with wrong layout events --- .../AnyBaseTableRow/AnyBaseTableRow.swift | 5 +- Sources/Classes/Views/BaseCell/BaseCell.swift | 46 +++++++++++++------ .../Classes/Views/EmptyCell/EmptyCell.swift | 24 +++++----- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift index 7814f12d..b85b82f7 100644 --- a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift +++ b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift @@ -45,9 +45,9 @@ private final class AnyBaseTableRowBox: AnyBaseTableRowHold public final class AnyBaseTableRow { fileprivate let anyTableRow: AnyBaseTableRowHolder - let viewModel: BaseCellViewModel + public let viewModel: BaseCellViewModel - init(tableRow: TableRow) where T: BaseCell, T.T: BaseCellViewModel { + public init(tableRow: TableRow) where T: BaseCell, T.T: BaseCellViewModel { anyTableRow = AnyBaseTableRowBox(tableRow: tableRow) viewModel = tableRow.item } @@ -61,3 +61,4 @@ public extension Array where Element == AnyBaseTableRow { } } + diff --git a/Sources/Classes/Views/BaseCell/BaseCell.swift b/Sources/Classes/Views/BaseCell/BaseCell.swift index f9424f0b..8d55b1f5 100644 --- a/Sources/Classes/Views/BaseCell/BaseCell.swift +++ b/Sources/Classes/Views/BaseCell/BaseCell.swift @@ -25,17 +25,11 @@ import TableKit open class BaseCell: UITableViewCell { + // public weak var viewModel: BaseCellViewModel? + public func configureSeparator(with viewModel: BaseCellViewModel) { - topView.isHidden = viewModel.separatorType.topIsHidden - bottomView.isHidden = viewModel.separatorType.bottomIsHidden - - topView.backgroundColor = viewModel.topSeparatorConfiguration?.color - topViewHeightConstraint.constant = viewModel.topSeparatorConfiguration?.height ?? CGFloat(pixels: 1) - topSeparatorInsets = viewModel.topSeparatorConfiguration?.insets ?? .zero - - bottomView.backgroundColor = viewModel.bottomSeparatorConfiguration?.color - bottomViewHeightConstraint.constant = viewModel.bottomSeparatorConfiguration?.height ?? CGFloat(pixels: 1) - bottomSeparatorInsets = viewModel.bottomSeparatorConfiguration?.insets ?? .zero + // self.viewModel = viewModel + configureInterface(with: viewModel) } // MARK: - Private @@ -73,12 +67,35 @@ open class BaseCell: UITableViewCell { super.updateConstraints() } - override open func awakeFromNib() { - super.awakeFromNib() + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) configureLineViews() } + public override init(style: UITableViewCellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + configureLineViews() + } + + private func configureInterface(with viewModel: BaseCellViewModel?) { + guard let viewModel = viewModel else { + return + } + + topView.isHidden = viewModel.separatorType.topIsHidden + bottomView.isHidden = viewModel.separatorType.bottomIsHidden + + topView.backgroundColor = viewModel.topSeparatorConfiguration?.color + topViewHeightConstraint.constant = viewModel.topSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + topSeparatorInsets = viewModel.topSeparatorConfiguration?.insets ?? .zero + + bottomView.backgroundColor = viewModel.bottomSeparatorConfiguration?.color + bottomViewHeightConstraint.constant = viewModel.bottomSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + bottomSeparatorInsets = viewModel.bottomSeparatorConfiguration?.insets ?? .zero + } + private func configureLineViews() { let requiredValues: [Any?] = [ topView, bottomView, @@ -101,6 +118,7 @@ open class BaseCell: UITableViewCell { view.backgroundColor = .black view.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(view) + contentView.bringSubview(toFront: view) return view } @@ -138,8 +156,8 @@ open class BaseCell: UITableViewCell { public extension TableRow where CellType.T: BaseCellViewModel { @discardableResult - func withSeparatorType(_ separatorType: CellSeparatorType) -> Self { - item.separatorType = separatorType + func with(separatorType: CellSeparatorType) -> Self { + item.with(separatorType: separatorType) return self } diff --git a/Sources/Classes/Views/EmptyCell/EmptyCell.swift b/Sources/Classes/Views/EmptyCell/EmptyCell.swift index 6a759c2d..02b52e8f 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCell.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCell.swift @@ -25,20 +25,21 @@ import TableKit public final class EmptyCell: BaseCell, ConfigurableCell { - private weak var coloredView: UIView! + private lazy var coloredView: UIView = { + let newView = UIView() + self.addSubview(newView) - override public func awakeFromNib() { - super.awakeFromNib() + newView.translatesAutoresizingMaskIntoConstraints = false + self.topAnchor.constraint(equalTo: newView.topAnchor).isActive = true + self.bottomAnchor.constraint(equalTo: newView.bottomAnchor).isActive = true + self.leadingAnchor.constraint(equalTo: newView.leadingAnchor).isActive = true + self.trailingAnchor.constraint(equalTo: newView.trailingAnchor).isActive = true - let view = UIView() - addSubview(view) + return newView + }() - topAnchor.constraint(equalTo: view.topAnchor).isActive = true - bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true - leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true - trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true - - coloredView = view + deinit { + debugPrint("Deinit") } public func configure(with viewModel: EmptyCellViewModel) { @@ -47,3 +48,4 @@ public final class EmptyCell: BaseCell, ConfigurableCell { } } + From e97a357e02431c85fa221365b63040124acc72bf Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 09:50:25 +0300 Subject: [PATCH 13/24] Update empty cell --- .../Classes/Views/EmptyCell/EmptyCell.swift | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/Sources/Classes/Views/EmptyCell/EmptyCell.swift b/Sources/Classes/Views/EmptyCell/EmptyCell.swift index 02b52e8f..a1cb8930 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCell.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCell.swift @@ -25,26 +25,11 @@ import TableKit public final class EmptyCell: BaseCell, ConfigurableCell { - private lazy var coloredView: UIView = { - let newView = UIView() - self.addSubview(newView) - - newView.translatesAutoresizingMaskIntoConstraints = false - self.topAnchor.constraint(equalTo: newView.topAnchor).isActive = true - self.bottomAnchor.constraint(equalTo: newView.bottomAnchor).isActive = true - self.leadingAnchor.constraint(equalTo: newView.leadingAnchor).isActive = true - self.trailingAnchor.constraint(equalTo: newView.trailingAnchor).isActive = true - - return newView - }() - - deinit { - debugPrint("Deinit") - } - public func configure(with viewModel: EmptyCellViewModel) { + backgroundColor = .clear + contentView.backgroundColor = viewModel.color + configureSeparator(with: viewModel) - coloredView.backgroundColor = viewModel.color } } From 47f942e3a5693130a245c274afa2b08e26771489 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 10:25:21 +0300 Subject: [PATCH 14/24] Fix code style & documentation --- .../AnyBaseTableRow/AnyBaseTableRow.swift | 12 +++- Sources/Classes/Views/BaseCell/BaseCell.swift | 68 ++++++++++--------- .../Views/BaseCell/BaseCellViewModel.swift | 12 ++-- .../Views/BaseCell/CellSeparatorType.swift | 20 +++--- .../BaseCell/SeparatorConfiguration.swift | 7 +- .../Classes/Views/EmptyCell/EmptyCell.swift | 3 +- .../Views/EmptyCell/EmptyCellRow.swift | 15 ++-- .../Views/EmptyCell/EmptyCellViewModel.swift | 5 ++ 8 files changed, 88 insertions(+), 54 deletions(-) diff --git a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift index b85b82f7..7e08e10d 100644 --- a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift +++ b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift @@ -45,8 +45,17 @@ private final class AnyBaseTableRowBox: AnyBaseTableRowHold public final class AnyBaseTableRow { fileprivate let anyTableRow: AnyBaseTableRowHolder + + /// Row `item`, that typed as BaseCellViewModel public let viewModel: BaseCellViewModel + /// TableRow that typed to generic Row + public var row: Row { + return anyTableRow.row + } + + /// Initialize AnyBaseTableRow with tableRow + /// - parameter tableRow: TableRow which `item` conforms to BaseCellViewModel public init(tableRow: TableRow) where T: BaseCell, T.T: BaseCellViewModel { anyTableRow = AnyBaseTableRowBox(tableRow: tableRow) viewModel = tableRow.item @@ -57,8 +66,7 @@ public final class AnyBaseTableRow { public extension Array where Element == AnyBaseTableRow { var rows: [Row] { - return map { $0.anyTableRow.row } + return map { $0.row } } } - diff --git a/Sources/Classes/Views/BaseCell/BaseCell.swift b/Sources/Classes/Views/BaseCell/BaseCell.swift index 8d55b1f5..6f9b482c 100644 --- a/Sources/Classes/Views/BaseCell/BaseCell.swift +++ b/Sources/Classes/Views/BaseCell/BaseCell.swift @@ -23,12 +23,14 @@ import UIKit import TableKit +/// Base cell that provides separator support open class BaseCell: UITableViewCell { - // public weak var viewModel: BaseCellViewModel? + // MARK: - Public + /// Configure separator with viewModel + /// - parameter viewModel: ViewModel of cell, that inherits from BaseCellViewModel public func configureSeparator(with viewModel: BaseCellViewModel) { - // self.viewModel = viewModel configureInterface(with: viewModel) } @@ -37,35 +39,25 @@ open class BaseCell: UITableViewCell { private var topView: UIView! private var bottomView: UIView! - // top separator + // top separator constraints private var topViewLeftConstraint: NSLayoutConstraint! private var topViewRightConstraint: NSLayoutConstraint! private var topViewTopConstraint: NSLayoutConstraint! - private var topViewHeightConstraint: NSLayoutConstraint! - // bottom separator + // bottom separator constraints private var bottomViewLeftConstraint: NSLayoutConstraint! private var bottomViewRightConstraint: NSLayoutConstraint! private var bottomViewBottomConstraint: NSLayoutConstraint! - private var bottomViewHeightConstraint: NSLayoutConstraint! - // insets - private var topSeparatorInsets = UIEdgeInsets.zero + private var topSeparatorInsets = UIEdgeInsets.zero private var bottomSeparatorInsets = UIEdgeInsets.zero - override open func updateConstraints() { - topViewTopConstraint.constant = topSeparatorInsets.top - topViewLeftConstraint.constant = topSeparatorInsets.left - topViewRightConstraint.constant = topSeparatorInsets.right + private var topSeparatorHeight = CGFloat(pixels: 1) + private var bottomSeparatorHeight = CGFloat(pixels: 1) - bottomViewLeftConstraint.constant = bottomSeparatorInsets.left - bottomViewRightConstraint.constant = bottomSeparatorInsets.right - bottomViewBottomConstraint.constant = bottomSeparatorInsets.bottom - - super.updateConstraints() - } + // MARK: - Initialization public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) @@ -79,21 +71,35 @@ open class BaseCell: UITableViewCell { configureLineViews() } + override open func updateConstraints() { + topViewTopConstraint.constant = topSeparatorInsets.top + topViewLeftConstraint.constant = topSeparatorInsets.left + topViewRightConstraint.constant = topSeparatorInsets.right + topViewHeightConstraint.constant = topSeparatorHeight + + bottomViewLeftConstraint.constant = bottomSeparatorInsets.left + bottomViewRightConstraint.constant = bottomSeparatorInsets.right + bottomViewBottomConstraint.constant = bottomSeparatorInsets.bottom + bottomViewHeightConstraint.constant = bottomSeparatorHeight + + super.updateConstraints() + } + private func configureInterface(with viewModel: BaseCellViewModel?) { guard let viewModel = viewModel else { return } - topView.isHidden = viewModel.separatorType.topIsHidden - bottomView.isHidden = viewModel.separatorType.bottomIsHidden + topView.isHidden = viewModel.separatorType.topIsHidden + bottomView.isHidden = viewModel.separatorType.bottomIsHidden - topView.backgroundColor = viewModel.topSeparatorConfiguration?.color - topViewHeightConstraint.constant = viewModel.topSeparatorConfiguration?.height ?? CGFloat(pixels: 1) - topSeparatorInsets = viewModel.topSeparatorConfiguration?.insets ?? .zero + topView.backgroundColor = viewModel.topSeparatorConfiguration?.color + topSeparatorHeight = viewModel.topSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + topSeparatorInsets = viewModel.topSeparatorConfiguration?.insets ?? .zero - bottomView.backgroundColor = viewModel.bottomSeparatorConfiguration?.color - bottomViewHeightConstraint.constant = viewModel.bottomSeparatorConfiguration?.height ?? CGFloat(pixels: 1) - bottomSeparatorInsets = viewModel.bottomSeparatorConfiguration?.insets ?? .zero + bottomView.backgroundColor = viewModel.bottomSeparatorConfiguration?.color + bottomSeparatorHeight = viewModel.bottomSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + bottomSeparatorInsets = viewModel.bottomSeparatorConfiguration?.insets ?? .zero } private func configureLineViews() { @@ -109,7 +115,7 @@ open class BaseCell: UITableViewCell { topView = createSeparatorView() bottomView = createSeparatorView() - configureConstrains() + createConstraints() } private func createSeparatorView() -> UIView { @@ -118,16 +124,16 @@ open class BaseCell: UITableViewCell { view.backgroundColor = .black view.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(view) - contentView.bringSubview(toFront: view) +// contentView.bringSubview(toFront: view) return view } - private func configureConstrains() { + private func createConstraints() { // height - topViewHeightConstraint = topView.heightAnchor.constraint(equalToConstant: CGFloat(pixels: 1)) + topViewHeightConstraint = topView.heightAnchor.constraint(equalToConstant: topSeparatorHeight) topViewHeightConstraint.isActive = true - bottomViewHeightConstraint = bottomView.heightAnchor.constraint(equalToConstant: CGFloat(pixels: 1)) + bottomViewHeightConstraint = bottomView.heightAnchor.constraint(equalToConstant: topSeparatorHeight) bottomViewHeightConstraint.isActive = true // top separator diff --git a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift index 5306b8ee..28d083a0 100644 --- a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift +++ b/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift @@ -25,13 +25,15 @@ import UIKit /// By default this class does not provide any separators open class BaseCellViewModel { - var separatorType = CellSeparatorType.none + internal var separatorType = CellSeparatorType.none - /// NOTE: Bottom dimension is ignored - var topSeparatorConfiguration: SeparatorConfiguration? + /// Configuration for topSeparator + /// - Importnat: Bottom dimension is ignored + internal var topSeparatorConfiguration: SeparatorConfiguration? - /// NOTE: Top dimension is ignored - var bottomSeparatorConfiguration: SeparatorConfiguration? + /// Configuration for topSeparator + /// - Importnat: Top dimension is ignored + internal var bottomSeparatorConfiguration: SeparatorConfiguration? public init() {} diff --git a/Sources/Classes/Views/BaseCell/CellSeparatorType.swift b/Sources/Classes/Views/BaseCell/CellSeparatorType.swift index df251706..97c9b803 100644 --- a/Sources/Classes/Views/BaseCell/CellSeparatorType.swift +++ b/Sources/Classes/Views/BaseCell/CellSeparatorType.swift @@ -22,14 +22,22 @@ import UIKit +/// Cell self-descriptive separator type public enum CellSeparatorType { + + /// All separators for cell hidden case none + + /// Show only top separator case top(SeparatorConfiguration) + + /// Show only bottom separator case bottom(SeparatorConfiguration) - /// Top than bottom + /// First configuration for top, second for bottom case full(SeparatorConfiguration, SeparatorConfiguration) + /// Determine if bottom separator is hidden public var bottomIsHidden: Bool { switch self { case .top, .none: @@ -39,6 +47,7 @@ public enum CellSeparatorType { } } + /// Determine if top separator is hidden public var topIsHidden: Bool { switch self { case .bottom, .none: @@ -48,13 +57,4 @@ public enum CellSeparatorType { } } - public var topConfiguration: SeparatorConfiguration? { - switch self { - case .top(let configuration), .full(let configuration, _): - return configuration - default: - return nil - } - } - } diff --git a/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift b/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift index 0af8a3c2..a6ebee80 100644 --- a/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift +++ b/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift @@ -22,16 +22,21 @@ import UIKit +/// Separator configuration. Supports positioning, color and height per each separator public struct SeparatorConfiguration { let color: UIColor let insets: UIEdgeInsets? let height: CGFloat + /// Initialize configuration with parameters + /// - parameter color: Color must be provided + /// - parameter insets: Insets for separator. Default is no insets + /// - parameter height: Height for separator. Default is 1 pixel + /// - returns: Ready to use separator configuration public init(color: UIColor, insets: UIEdgeInsets? = .zero, height: CGFloat = CGFloat(pixels: 1)) { self.color = color self.insets = insets self.height = height } - public static let baseConfiguration = SeparatorConfiguration(color: .black, insets: .zero) } diff --git a/Sources/Classes/Views/EmptyCell/EmptyCell.swift b/Sources/Classes/Views/EmptyCell/EmptyCell.swift index a1cb8930..c8ed04b6 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCell.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCell.swift @@ -23,6 +23,8 @@ import UIKit import TableKit +/// Empty cell class. Do not use it directly. +/// - see: `EmptyCellRow` public final class EmptyCell: BaseCell, ConfigurableCell { public func configure(with viewModel: EmptyCellViewModel) { @@ -33,4 +35,3 @@ public final class EmptyCell: BaseCell, ConfigurableCell { } } - diff --git a/Sources/Classes/Views/EmptyCell/EmptyCellRow.swift b/Sources/Classes/Views/EmptyCell/EmptyCellRow.swift index b0a64a95..edb3da7b 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCellRow.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCellRow.swift @@ -22,10 +22,17 @@ import TableKit -/// Row that simulates spacing, can end editing on click, specify this in constructor +/// Class that +/// - Simulates spacing with no-breaking constraints +/// - Can end editing on click public final class EmptyCellRow: TableRow { - public convenience init(with height: CGFloat, + /// Provide height with color to create row + /// - parameter height: Height of row + /// - parameter color: Color of row + /// - parameter endEditingOnClick: Will cell end editing for neighbour currently active UIControl subclasses + /// - returns: Fully configured EmptyCellRow + public convenience init(height: CGFloat, color: UIColor = .clear, endEditingOnClick: Bool = false) { @@ -38,12 +45,12 @@ public final class EmptyCellRow: TableRow { } } - // Used for set custom height to each cell, not for each cell type + /// Used for set custom height to each cell, not for each cell type override public var defaultHeight: CGFloat? { return item.height } - /// - returns: EmptyCellRow typed as AnyBaseTableRow + /// EmptyCellRow typed as AnyBaseTableRow public var anyRow: AnyBaseTableRow { return AnyBaseTableRow(tableRow: self) } diff --git a/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift b/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift index 6508837f..d185804c 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift @@ -22,11 +22,16 @@ import UIKit +/// ViewModel for EmptyCell public final class EmptyCellViewModel: BaseCellViewModel { let color: UIColor let height: CGFloat + /// Returns configured ViewModel for cell + /// - parameter height: Height of cell + /// - parameter color: Fill color of cell + /// - returns: Configured ViewModel public init(height: CGFloat, color: UIColor = .clear) { self.color = color self.height = height From 1b16b2435aab500511c6089ac07ef53dee67350e Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 13:29:37 +0300 Subject: [PATCH 15/24] Update for code-review --- LeadKit.xcodeproj/project.pbxproj | 36 +++++++++------- .../AnyBaseTableRow/AnyBaseTableRow.swift | 7 ++-- .../Classes/Views/EmptyCell/EmptyCell.swift | 2 +- .../Views/EmptyCell/EmptyCellViewModel.swift | 2 +- .../CellSeparatorType.swift | 4 +- .../SeparatorCell.swift} | 41 ++++++++----------- .../SeparatorCellViewModel.swift} | 4 +- .../SeparatorConfiguration.swift | 0 .../Comparable/Comparable+Extensions.swift | 3 ++ .../TableDirector/TableRow+Extensions.swift | 33 +++++++++++++++ 10 files changed, 85 insertions(+), 47 deletions(-) rename Sources/Classes/Views/{BaseCell => SeparatorCell}/CellSeparatorType.swift (97%) rename Sources/Classes/Views/{BaseCell/BaseCell.swift => SeparatorCell/SeparatorCell.swift} (87%) rename Sources/Classes/Views/{BaseCell/BaseCellViewModel.swift => SeparatorCell/SeparatorCellViewModel.swift} (97%) rename Sources/Classes/Views/{BaseCell => SeparatorCell}/SeparatorConfiguration.swift (100%) create mode 100644 Sources/Extensions/TableDirector/TableRow+Extensions.swift diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index 8d6d6e61..869c9e22 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -384,6 +384,8 @@ 67E6C2371EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 67E6C2381EBB32F5007842A6 /* SingleLoadCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67E6C2341EBB32F5007842A6 /* SingleLoadCursor.swift */; }; 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; }; + A658E54D1F8CD7790093527A /* TableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */; }; + A658E54E1F8CD7790093527A /* TableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */; }; A6C9A4FA1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; A6C9A4FB1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; A6C9A5041F8BC78F009311CC /* CellSeparatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */; }; @@ -396,11 +398,11 @@ A6C9A5111F8BC79D009311CC /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; A6D10EAB1F8A9278003E69DD /* Comparable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */; }; A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; }; - A6E0DDDF1F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; - A6E0DDE01F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; + A6E0DDDF1F8A696F002CA74E /* SeparatorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* SeparatorCell.swift */; }; + A6E0DDE01F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */; }; A6E0DDE11F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; - A6E0DDE31F8A696F002CA74E /* BaseCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* BaseCell.swift */; }; - A6E0DDE41F8A696F002CA74E /* BaseCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* BaseCellViewModel.swift */; }; + A6E0DDE31F8A696F002CA74E /* SeparatorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* SeparatorCell.swift */; }; + A6E0DDE41F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */; }; A6E0DDE51F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */; }; A6E0DDEF1F8A6C57002CA74E /* CellSeparatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */; }; A6E0DDF11F8A6C80002CA74E /* SeparatorConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */; }; @@ -596,8 +598,9 @@ 887F99C5326BD220C2811BD6 /* Pods_LeadKit_LeadKit_iOS_Extensions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_iOS_Extensions.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 95E457F1241D136396FC2420 /* Pods_LeadKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9966FB938D114F79F71AE037 /* Pods-LeadKit-LeadKit iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit-LeadKit iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit-LeadKit iOS/Pods-LeadKit-LeadKit iOS.release.xcconfig"; sourceTree = ""; }; - A66428A51F8A653500C6308D /* BaseCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCellViewModel.swift; sourceTree = ""; }; - A66428A61F8A653600C6308D /* BaseCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCell.swift; sourceTree = ""; }; + A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TableRow+Extensions.swift"; sourceTree = ""; }; + A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCellViewModel.swift; sourceTree = ""; }; + A66428A61F8A653600C6308D /* SeparatorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCell.swift; sourceTree = ""; }; A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = ""; }; A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyBaseTableRow.swift; sourceTree = ""; }; A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellViewModel.swift; sourceTree = ""; }; @@ -748,7 +751,7 @@ isa = PBXGroup; children = ( A6AF3B381F8B957400CDB971 /* AnyBaseTableRow */, - A66428A41F8A651700C6308D /* BaseCell */, + A66428A41F8A651700C6308D /* SeparatorCell */, A6C9A4F71F8BBC0F009311CC /* EmptyCell */, A6C9A4F81F8BBC27009311CC /* SpinnerView */, A6C9A4F91F8BBCCE009311CC /* XibView */, @@ -939,6 +942,7 @@ isa = PBXGroup; children = ( 671462011EB3396E00EAB194 /* TableDirector+Extensions.swift */, + A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */, ); path = TableDirector; sourceTree = ""; @@ -1255,15 +1259,15 @@ path = Single; sourceTree = ""; }; - A66428A41F8A651700C6308D /* BaseCell */ = { + A66428A41F8A651700C6308D /* SeparatorCell */ = { isa = PBXGroup; children = ( - A66428A61F8A653600C6308D /* BaseCell.swift */, - A66428A51F8A653500C6308D /* BaseCellViewModel.swift */, + A66428A61F8A653600C6308D /* SeparatorCell.swift */, + A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */, A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */, A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */, ); - path = BaseCell; + path = SeparatorCell; sourceTree = ""; }; A6AF3B381F8B957400CDB971 /* AnyBaseTableRow */ = { @@ -2114,6 +2118,7 @@ 671462D01EB3396E00EAB194 /* UIScrollView+Support.swift in Sources */, 671463901EB3396E00EAB194 /* TemplateDrawingOperation.swift in Sources */, 6714630C1EB3396E00EAB194 /* UIViewController+DefaultStoryboardIdentifier.swift in Sources */, + A658E54D1F8CD7790093527A /* TableRow+Extensions.swift in Sources */, 671462981EB3396E00EAB194 /* CGSize+Resize.swift in Sources */, 671462F81EB3396E00EAB194 /* UIView+DefaultReuseIdentifier.swift in Sources */, 67051ADB1EBC7C36008EADC0 /* SpinnerView.swift in Sources */, @@ -2130,7 +2135,7 @@ 671462E01EB3396E00EAB194 /* UICollectionView+CellRegistration.swift in Sources */, 671462601EB3396E00EAB194 /* PaginationTableViewWrapper.swift in Sources */, 671463281EB3396E00EAB194 /* BaseViewModel.swift in Sources */, - A6E0DDDF1F8A696F002CA74E /* BaseCell.swift in Sources */, + A6E0DDDF1F8A696F002CA74E /* SeparatorCell.swift in Sources */, 671462AC1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */, 671463001EB3396E00EAB194 /* UIView+LoadFromNib.swift in Sources */, 6714627C1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */, @@ -2168,7 +2173,7 @@ A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */, 671462881EB3396E00EAB194 /* CGFloat+Pixels.swift in Sources */, 671462941EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */, - A6E0DDE01F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, + A6E0DDE01F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */, 671463641EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */, 671462481EB3396E00EAB194 /* FixedPageCursor.swift in Sources */, 671462C81EB3396E00EAB194 /* String+Localization.swift in Sources */, @@ -2208,12 +2213,13 @@ A6C9A50E1F8BC799009311CC /* EmptyCellRow.swift in Sources */, A6C9A50C1F8BC799009311CC /* EmptyCell.swift in Sources */, 671463B81EB34B1E00EAB194 /* StubCursor.swift in Sources */, - A6E0DDE41F8A696F002CA74E /* BaseCellViewModel.swift in Sources */, + A658E54E1F8CD7790093527A /* TableRow+Extensions.swift in Sources */, + A6E0DDE41F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */, 671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */, A6F32C101F6EBE9600AC08EE /* StringExtensionTests.swift in Sources */, 671463C11EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, 671463BE1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */, - A6E0DDE31F8A696F002CA74E /* BaseCell.swift in Sources */, + A6E0DDE31F8A696F002CA74E /* SeparatorCell.swift in Sources */, A6C9A50F1F8BC79D009311CC /* Comparable+Extensions.swift in Sources */, 671463C41EB34B1E00EAB194 /* Post.swift in Sources */, A6E0DDE51F8A696F002CA74E /* AnyBaseTableRow.swift in Sources */, diff --git a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift index 7e08e10d..4ac6d62d 100644 --- a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift +++ b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift @@ -32,7 +32,8 @@ private class AnyBaseTableRowHolder { } /// Class used to hold resolved TableRow -private final class AnyBaseTableRowBox: AnyBaseTableRowHolder where T: BaseCell, T.T: BaseCellViewModel { +private final class AnyBaseTableRowBox: AnyBaseTableRowHolder + where T: SeparatorCell, T.T: SeparatorCellViewModel { init(tableRow: TableRow) { super.init(tableRow: tableRow) @@ -47,7 +48,7 @@ public final class AnyBaseTableRow { fileprivate let anyTableRow: AnyBaseTableRowHolder /// Row `item`, that typed as BaseCellViewModel - public let viewModel: BaseCellViewModel + public let viewModel: SeparatorCellViewModel /// TableRow that typed to generic Row public var row: Row { @@ -56,7 +57,7 @@ public final class AnyBaseTableRow { /// Initialize AnyBaseTableRow with tableRow /// - parameter tableRow: TableRow which `item` conforms to BaseCellViewModel - public init(tableRow: TableRow) where T: BaseCell, T.T: BaseCellViewModel { + public init(tableRow: TableRow) where T: SeparatorCell, T.T: SeparatorCellViewModel { anyTableRow = AnyBaseTableRowBox(tableRow: tableRow) viewModel = tableRow.item } diff --git a/Sources/Classes/Views/EmptyCell/EmptyCell.swift b/Sources/Classes/Views/EmptyCell/EmptyCell.swift index c8ed04b6..be80560e 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCell.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCell.swift @@ -25,7 +25,7 @@ import TableKit /// Empty cell class. Do not use it directly. /// - see: `EmptyCellRow` -public final class EmptyCell: BaseCell, ConfigurableCell { +public final class EmptyCell: SeparatorCell, ConfigurableCell { public func configure(with viewModel: EmptyCellViewModel) { backgroundColor = .clear diff --git a/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift b/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift index d185804c..1c7d7281 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCellViewModel.swift @@ -23,7 +23,7 @@ import UIKit /// ViewModel for EmptyCell -public final class EmptyCellViewModel: BaseCellViewModel { +public final class EmptyCellViewModel: SeparatorCellViewModel { let color: UIColor let height: CGFloat diff --git a/Sources/Classes/Views/BaseCell/CellSeparatorType.swift b/Sources/Classes/Views/SeparatorCell/CellSeparatorType.swift similarity index 97% rename from Sources/Classes/Views/BaseCell/CellSeparatorType.swift rename to Sources/Classes/Views/SeparatorCell/CellSeparatorType.swift index 97c9b803..e85cadc5 100644 --- a/Sources/Classes/Views/BaseCell/CellSeparatorType.swift +++ b/Sources/Classes/Views/SeparatorCell/CellSeparatorType.swift @@ -42,7 +42,7 @@ public enum CellSeparatorType { switch self { case .top, .none: return true - default: + case .bottom, .full: return false } } @@ -52,7 +52,7 @@ public enum CellSeparatorType { switch self { case .bottom, .none: return true - default: + case .top, .full: return false } } diff --git a/Sources/Classes/Views/BaseCell/BaseCell.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift similarity index 87% rename from Sources/Classes/Views/BaseCell/BaseCell.swift rename to Sources/Classes/Views/SeparatorCell/SeparatorCell.swift index 6f9b482c..ce8c04c7 100644 --- a/Sources/Classes/Views/BaseCell/BaseCell.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift @@ -24,16 +24,31 @@ import UIKit import TableKit /// Base cell that provides separator support -open class BaseCell: UITableViewCell { +/// Take note that separators are simple views, that located on contentView, +/// so if you hide that with another view that fully hide +/// you can use that method `moveSeparators(to:)` +open class SeparatorCell: UITableViewCell { // MARK: - Public /// Configure separator with viewModel /// - parameter viewModel: ViewModel of cell, that inherits from BaseCellViewModel - public func configureSeparator(with viewModel: BaseCellViewModel) { + public func configureSeparator(with viewModel: SeparatorCellViewModel) { configureInterface(with: viewModel) } + /// Use this function to place separator at hierarchy + /// - parameter front: Move separator to front or bottom in heirarchy + public func moveSeparators(to front: Bool) { + if front { + contentView.bringSubview(toFront: topView) + contentView.bringSubview(toFront: bottomView) + } else { + contentView.sendSubview(toBack: topView) + contentView.sendSubview(toBack: bottomView) + } + } + // MARK: - Private private var topView: UIView! @@ -85,7 +100,7 @@ open class BaseCell: UITableViewCell { super.updateConstraints() } - private func configureInterface(with viewModel: BaseCellViewModel?) { + private func configureInterface(with viewModel: SeparatorCellViewModel?) { guard let viewModel = viewModel else { return } @@ -103,15 +118,6 @@ open class BaseCell: UITableViewCell { } private func configureLineViews() { - let requiredValues: [Any?] = [ - topView, bottomView, - topViewLeftConstraint, topViewRightConstraint, topViewTopConstraint, - bottomViewLeftConstraint, bottomViewRightConstraint, bottomViewBottomConstraint] - - if !requiredValues.contains(where: { $0 == nil }) { - return - } - topView = createSeparatorView() bottomView = createSeparatorView() @@ -124,7 +130,6 @@ open class BaseCell: UITableViewCell { view.backgroundColor = .black view.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(view) -// contentView.bringSubview(toFront: view) return view } @@ -158,13 +163,3 @@ open class BaseCell: UITableViewCell { } } - -public extension TableRow where CellType.T: BaseCellViewModel { - - @discardableResult - func with(separatorType: CellSeparatorType) -> Self { - item.with(separatorType: separatorType) - return self - } - -} diff --git a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift similarity index 97% rename from Sources/Classes/Views/BaseCell/BaseCellViewModel.swift rename to Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift index 28d083a0..40062507 100644 --- a/Sources/Classes/Views/BaseCell/BaseCellViewModel.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift @@ -23,7 +23,7 @@ import UIKit /// By default this class does not provide any separators -open class BaseCellViewModel { +open class SeparatorCellViewModel { internal var separatorType = CellSeparatorType.none @@ -51,7 +51,7 @@ open class BaseCellViewModel { case .full(let top, let bottom): topSeparatorConfiguration = top bottomSeparatorConfiguration = bottom - default: + case .none: topSeparatorConfiguration = nil bottomSeparatorConfiguration = nil } diff --git a/Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift b/Sources/Classes/Views/SeparatorCell/SeparatorConfiguration.swift similarity index 100% rename from Sources/Classes/Views/BaseCell/SeparatorConfiguration.swift rename to Sources/Classes/Views/SeparatorCell/SeparatorConfiguration.swift diff --git a/Sources/Extensions/Comparable/Comparable+Extensions.swift b/Sources/Extensions/Comparable/Comparable+Extensions.swift index 9589de93..4c49811e 100644 --- a/Sources/Extensions/Comparable/Comparable+Extensions.swift +++ b/Sources/Extensions/Comparable/Comparable+Extensions.swift @@ -24,6 +24,9 @@ import Foundation public extension Comparable { + /// Use this function to restrict comparable with lower and upper values + /// - parameter bounds: Lower and uppper bounds tuple + /// - returns: Current value if it fits range, otherwise lower if value is too small or upper if value is too big func `in`(bounds: (lower: Self, upper: Self)) -> Self { return min(max(bounds.lower, self), bounds.upper) } diff --git a/Sources/Extensions/TableDirector/TableRow+Extensions.swift b/Sources/Extensions/TableDirector/TableRow+Extensions.swift new file mode 100644 index 00000000..aafee926 --- /dev/null +++ b/Sources/Extensions/TableDirector/TableRow+Extensions.swift @@ -0,0 +1,33 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import TableKit + +public extension TableRow where CellType.T: SeparatorCellViewModel { + + @discardableResult + func with(separatorType: CellSeparatorType) -> Self { + item.with(separatorType: separatorType) + return self + } + +} From 24ae2c51603362656e1b660ce47cd4b4caa93b41 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 13:47:43 +0300 Subject: [PATCH 16/24] Add extension + update podspec --- LeadKit.podspec | 7 ++-- LeadKit.xcodeproj/project.pbxproj | 6 ++++ .../AnyBaseTableRow/AnyBaseTableRow.swift | 10 +----- .../Views/SeparatorCell/SeparatorCell.swift | 7 ++-- .../Array+AnyBaseTableRow+Extensions.swift | 32 +++++++++++++++++++ .../TableDirector+Extensions.swift | 27 ++++++++++++++++ 6 files changed, 75 insertions(+), 14 deletions(-) create mode 100644 Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift diff --git a/LeadKit.podspec b/LeadKit.podspec index 586ef82f..842d3ddc 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -53,7 +53,8 @@ Pod::Spec.new do |s| "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", "Sources/Extensions/StoryboardProtocol/*", "Sources/Extensions/Support/UIScrollView+Support.swift", - "Sources/Extensions/TableDirector/TableDirector+Extensions.swift", + "Sources/Extensions/TableDirector/*", + "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift" "Sources/Extensions/UIActivityIndicatorView/*", "Sources/Extensions/UIAlertcontroller/*", "Sources/Extensions/UICollectionView/*", @@ -79,7 +80,8 @@ Pod::Spec.new do |s| "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", "Sources/Extensions/Support/UIScrollView+Support.swift", - "Sources/Extensions/TableDirector/TableDirector+Extensions.swift", + "Sources/Extensions/TableDirector/*", + "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift" ] ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0' @@ -105,6 +107,7 @@ Pod::Spec.new do |s| "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", "Sources/Extensions/TableDirector/TableDirector+Extensions.swift", + "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift" ] ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0' diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index 869c9e22..fd941c61 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -386,6 +386,8 @@ 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; }; A658E54D1F8CD7790093527A /* TableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */; }; A658E54E1F8CD7790093527A /* TableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */; }; + A658E5501F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */; }; + A658E5511F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */; }; A6C9A4FA1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; A6C9A4FB1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; A6C9A5041F8BC78F009311CC /* CellSeparatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */; }; @@ -599,6 +601,7 @@ 95E457F1241D136396FC2420 /* Pods_LeadKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9966FB938D114F79F71AE037 /* Pods-LeadKit-LeadKit iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit-LeadKit iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit-LeadKit iOS/Pods-LeadKit-LeadKit iOS.release.xcconfig"; sourceTree = ""; }; A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TableRow+Extensions.swift"; sourceTree = ""; }; + A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+AnyBaseTableRow+Extensions.swift"; sourceTree = ""; }; A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCellViewModel.swift; sourceTree = ""; }; A66428A61F8A653600C6308D /* SeparatorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCell.swift; sourceTree = ""; }; A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = ""; }; @@ -1365,6 +1368,7 @@ isa = PBXGroup; children = ( EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */, + A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */, ); path = Array; sourceTree = ""; @@ -2150,6 +2154,7 @@ 671463041EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671463701EB3396E00EAB194 /* ApiRequestParameters.swift in Sources */, + A658E5501F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */, 671462EC1EB3396E00EAB194 /* UIImage+Extensions.swift in Sources */, A6E0DDF11F8A6C80002CA74E /* SeparatorConfiguration.swift in Sources */, 6714636C1EB3396E00EAB194 /* XibNameProtocol.swift in Sources */, @@ -2215,6 +2220,7 @@ 671463B81EB34B1E00EAB194 /* StubCursor.swift in Sources */, A658E54E1F8CD7790093527A /* TableRow+Extensions.swift in Sources */, A6E0DDE41F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */, + A658E5511F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */, 671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */, A6F32C101F6EBE9600AC08EE /* StringExtensionTests.swift in Sources */, 671463C11EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, diff --git a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift index 4ac6d62d..70810c57 100644 --- a/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift +++ b/Sources/Classes/Views/AnyBaseTableRow/AnyBaseTableRow.swift @@ -45,7 +45,7 @@ private final class AnyBaseTableRowBox: AnyBaseTableRowHold /// Holds TableRow with any model inherited from BaseCellViewModel public final class AnyBaseTableRow { - fileprivate let anyTableRow: AnyBaseTableRowHolder + private let anyTableRow: AnyBaseTableRowHolder /// Row `item`, that typed as BaseCellViewModel public let viewModel: SeparatorCellViewModel @@ -63,11 +63,3 @@ public final class AnyBaseTableRow { } } - -public extension Array where Element == AnyBaseTableRow { - - var rows: [Row] { - return map { $0.row } - } - -} diff --git a/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift index ce8c04c7..792349d6 100644 --- a/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift @@ -24,9 +24,10 @@ import UIKit import TableKit /// Base cell that provides separator support -/// Take note that separators are simple views, that located on contentView, -/// so if you hide that with another view that fully hide -/// you can use that method `moveSeparators(to:)` +/// Take note that: +/// - in `configure(with:)` you must call `configureSeparator(with:)` +/// - separators are simple views, that located on `contentView`. +/// - if you hide that with another view that fully hide you can use that method `moveSeparators(to:)` open class SeparatorCell: UITableViewCell { // MARK: - Public diff --git a/Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift b/Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift new file mode 100644 index 00000000..2a66cc04 --- /dev/null +++ b/Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 Touch Instinct +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the Software), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +import TableKit + +public extension Array where Element == AnyBaseTableRow { + + /// Create rows from anyBaseTableRow array + var rows: [Row] { + return map { $0.row } + } + +} diff --git a/Sources/Extensions/TableDirector/TableDirector+Extensions.swift b/Sources/Extensions/TableDirector/TableDirector+Extensions.swift index bc00d2aa..4dc2dbc8 100644 --- a/Sources/Extensions/TableDirector/TableDirector+Extensions.swift +++ b/Sources/Extensions/TableDirector/TableDirector+Extensions.swift @@ -112,3 +112,30 @@ public extension TableDirector { } } + +// MARK: - Separator Configuration + +public extension TableDirector { + + /// Configure separators for bunch of rows in array + /// - parameter rows: Rows for configuration + /// - parameter extreme: Configuration that will be used for extreme values, for first or last row + /// - parameter middle: Configuration for intermediate rows + func configure(rows: [AnyBaseTableRow], + extreme extremeSeparatorConfiguration: SeparatorConfiguration, + middle middleSeparatorConfiguration: SeparatorConfiguration) { + + if rows.isEmpty { + return + } + + switch rows.count { + case 1: + rows.first?.viewModel.with(separatorType: .full(extremeSeparatorConfiguration, extremeSeparatorConfiguration)) + default: + rows.forEach { $0.viewModel.with(separatorType: .full(middleSeparatorConfiguration, middleSeparatorConfiguration))} + rows.first?.viewModel.with(separatorType: .top(extremeSeparatorConfiguration)) + rows.last?.viewModel.with(separatorType: .bottom(extremeSeparatorConfiguration)) + } + } +} From 54ba8531b7bd16f83938caae8ff061164f12087a Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 13:53:24 +0300 Subject: [PATCH 17/24] Update for code-review --- .../SeparatorCell/CellSeparatorType.swift | 7 +++++-- .../Views/SeparatorCell/SeparatorCell.swift | 20 ++++++++++--------- .../SeparatorCellViewModel.swift | 9 +++++---- .../TableDirector+Extensions.swift | 8 ++++---- .../TableDirector/TableRow+Extensions.swift | 6 ++---- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Sources/Classes/Views/SeparatorCell/CellSeparatorType.swift b/Sources/Classes/Views/SeparatorCell/CellSeparatorType.swift index e85cadc5..4b9cf952 100644 --- a/Sources/Classes/Views/SeparatorCell/CellSeparatorType.swift +++ b/Sources/Classes/Views/SeparatorCell/CellSeparatorType.swift @@ -36,9 +36,12 @@ public enum CellSeparatorType { /// First configuration for top, second for bottom case full(SeparatorConfiguration, SeparatorConfiguration) +} + +public extension CellSeparatorType { /// Determine if bottom separator is hidden - public var bottomIsHidden: Bool { + var bottomIsHidden: Bool { switch self { case .top, .none: return true @@ -48,7 +51,7 @@ public enum CellSeparatorType { } /// Determine if top separator is hidden - public var topIsHidden: Bool { + var topIsHidden: Bool { switch self { case .bottom, .none: return true diff --git a/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift index 792349d6..2b9d0d60 100644 --- a/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift @@ -23,6 +23,10 @@ import UIKit import TableKit +private enum Constants { + static let defaultSeparatorHeight = CGFloat(pixels: 1) +} + /// Base cell that provides separator support /// Take note that: /// - in `configure(with:)` you must call `configureSeparator(with:)` @@ -70,8 +74,8 @@ open class SeparatorCell: UITableViewCell { private var topSeparatorInsets = UIEdgeInsets.zero private var bottomSeparatorInsets = UIEdgeInsets.zero - private var topSeparatorHeight = CGFloat(pixels: 1) - private var bottomSeparatorHeight = CGFloat(pixels: 1) + private var topSeparatorHeight = Constants.defaultSeparatorHeight + private var bottomSeparatorHeight = Constants.defaultSeparatorHeight // MARK: - Initialization @@ -101,20 +105,18 @@ open class SeparatorCell: UITableViewCell { super.updateConstraints() } - private func configureInterface(with viewModel: SeparatorCellViewModel?) { - guard let viewModel = viewModel else { - return - } + // MARK: - Private + private func configureInterface(with viewModel: SeparatorCellViewModel) { topView.isHidden = viewModel.separatorType.topIsHidden bottomView.isHidden = viewModel.separatorType.bottomIsHidden topView.backgroundColor = viewModel.topSeparatorConfiguration?.color - topSeparatorHeight = viewModel.topSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + topSeparatorHeight = viewModel.topSeparatorConfiguration?.height ?? Constants.defaultSeparatorHeight topSeparatorInsets = viewModel.topSeparatorConfiguration?.insets ?? .zero bottomView.backgroundColor = viewModel.bottomSeparatorConfiguration?.color - bottomSeparatorHeight = viewModel.bottomSeparatorConfiguration?.height ?? CGFloat(pixels: 1) + bottomSeparatorHeight = viewModel.bottomSeparatorConfiguration?.height ?? Constants.defaultSeparatorHeight bottomSeparatorInsets = viewModel.bottomSeparatorConfiguration?.insets ?? .zero } @@ -139,7 +141,7 @@ open class SeparatorCell: UITableViewCell { topViewHeightConstraint = topView.heightAnchor.constraint(equalToConstant: topSeparatorHeight) topViewHeightConstraint.isActive = true - bottomViewHeightConstraint = bottomView.heightAnchor.constraint(equalToConstant: topSeparatorHeight) + bottomViewHeightConstraint = bottomView.heightAnchor.constraint(equalToConstant: bottomSeparatorHeight) bottomViewHeightConstraint.isActive = true // top separator diff --git a/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift index 40062507..ded62dcd 100644 --- a/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift @@ -37,8 +37,11 @@ open class SeparatorCellViewModel { public init() {} - @discardableResult - public func with(separatorType: CellSeparatorType) -> Self { +} + +public extension SeparatorCellViewModel { + + func set(separatorType: CellSeparatorType) { self.separatorType = separatorType switch separatorType { @@ -55,8 +58,6 @@ open class SeparatorCellViewModel { topSeparatorConfiguration = nil bottomSeparatorConfiguration = nil } - - return self } } diff --git a/Sources/Extensions/TableDirector/TableDirector+Extensions.swift b/Sources/Extensions/TableDirector/TableDirector+Extensions.swift index 4dc2dbc8..2010e557 100644 --- a/Sources/Extensions/TableDirector/TableDirector+Extensions.swift +++ b/Sources/Extensions/TableDirector/TableDirector+Extensions.swift @@ -131,11 +131,11 @@ public extension TableDirector { switch rows.count { case 1: - rows.first?.viewModel.with(separatorType: .full(extremeSeparatorConfiguration, extremeSeparatorConfiguration)) + rows.first?.viewModel.set(separatorType: .full(extremeSeparatorConfiguration, extremeSeparatorConfiguration)) default: - rows.forEach { $0.viewModel.with(separatorType: .full(middleSeparatorConfiguration, middleSeparatorConfiguration))} - rows.first?.viewModel.with(separatorType: .top(extremeSeparatorConfiguration)) - rows.last?.viewModel.with(separatorType: .bottom(extremeSeparatorConfiguration)) + rows.forEach { $0.viewModel.set(separatorType: .full(middleSeparatorConfiguration, middleSeparatorConfiguration))} + rows.first?.viewModel.set(separatorType: .top(extremeSeparatorConfiguration)) + rows.last?.viewModel.set(separatorType: .bottom(extremeSeparatorConfiguration)) } } } diff --git a/Sources/Extensions/TableDirector/TableRow+Extensions.swift b/Sources/Extensions/TableDirector/TableRow+Extensions.swift index aafee926..35c157d2 100644 --- a/Sources/Extensions/TableDirector/TableRow+Extensions.swift +++ b/Sources/Extensions/TableDirector/TableRow+Extensions.swift @@ -24,10 +24,8 @@ import TableKit public extension TableRow where CellType.T: SeparatorCellViewModel { - @discardableResult - func with(separatorType: CellSeparatorType) -> Self { - item.with(separatorType: separatorType) - return self + func with(separatorType: CellSeparatorType) { + item.set(separatorType: separatorType) } } From 9e959a4fdf6cf525a11866e24ead4bcb29d112e8 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 13:54:56 +0300 Subject: [PATCH 18/24] Fix podspec --- LeadKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LeadKit.podspec b/LeadKit.podspec index 842d3ddc..c66716ff 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -54,7 +54,7 @@ Pod::Spec.new do |s| "Sources/Extensions/StoryboardProtocol/*", "Sources/Extensions/Support/UIScrollView+Support.swift", "Sources/Extensions/TableDirector/*", - "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift" + "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift", "Sources/Extensions/UIActivityIndicatorView/*", "Sources/Extensions/UIAlertcontroller/*", "Sources/Extensions/UICollectionView/*", From 5b2b892a5970382ac64c23836526e15fad09181d Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 14:02:30 +0300 Subject: [PATCH 19/24] Rename initializer --- CHANGELOG.md | 5 ++++- LeadKit.podspec | 6 +++--- Sources/Classes/Cursors/FixedPageCursor.swift | 2 +- Sources/Classes/Cursors/MapCursor.swift | 2 +- Sources/Classes/Cursors/SingleLoadCursor.swift | 2 +- Sources/Classes/Cursors/StaticCursor.swift | 2 +- Sources/Protocols/ResettableType.swift | 4 ++-- Tests/Cursors/StubCursor.swift | 2 +- 8 files changed, 14 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e85c587d..32a6b3e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,4 +22,7 @@ ## 0.5.11 -- **Add**: `BaseCell`, `AnyBaseTableRow`, `EmptyCell`, `EmptyCellRow` \ No newline at end of file +- **[Breaking Change]**: rename initializer from `init(initialFrom:)` to `init(resetFrom:)` in `ResettableType` +- **Add**: `SeparatorCell` with `SeparatorCellViewModel` +- **Add**: `AnyBaseTableRow` for type-erasure +- **Add**: `EmptyCellRow` for empty cell with static height \ No newline at end of file diff --git a/LeadKit.podspec b/LeadKit.podspec index c66716ff..5dabb07d 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -54,7 +54,7 @@ Pod::Spec.new do |s| "Sources/Extensions/StoryboardProtocol/*", "Sources/Extensions/Support/UIScrollView+Support.swift", "Sources/Extensions/TableDirector/*", - "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift", + "Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift", "Sources/Extensions/UIActivityIndicatorView/*", "Sources/Extensions/UIAlertcontroller/*", "Sources/Extensions/UICollectionView/*", @@ -81,7 +81,7 @@ Pod::Spec.new do |s| "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", "Sources/Extensions/Support/UIScrollView+Support.swift", "Sources/Extensions/TableDirector/*", - "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift" + "Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift" ] ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0' @@ -107,7 +107,7 @@ Pod::Spec.new do |s| "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", "Sources/Extensions/TableDirector/TableDirector+Extensions.swift", - "Sources/Structures/Array/Array+AnyBaseTableRow+Extensions.swift" + "Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift" ] ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0' diff --git a/Sources/Classes/Cursors/FixedPageCursor.swift b/Sources/Classes/Cursors/FixedPageCursor.swift index 22a6a1b8..8bc726f5 100644 --- a/Sources/Classes/Cursors/FixedPageCursor.swift +++ b/Sources/Classes/Cursors/FixedPageCursor.swift @@ -80,7 +80,7 @@ public class ResettableFixedPageCursor: FixedPageC super.init(cursor: cursor, pageSize: pageSize) } - public required init(initialFrom other: ResettableFixedPageCursor) { + public required init(resetFrom other: ResettableFixedPageCursor) { super.init(cursor: other.cursor.reset(), pageSize: other.pageSize) } diff --git a/Sources/Classes/Cursors/MapCursor.swift b/Sources/Classes/Cursors/MapCursor.swift index bc83026d..69647bc9 100644 --- a/Sources/Classes/Cursors/MapCursor.swift +++ b/Sources/Classes/Cursors/MapCursor.swift @@ -95,7 +95,7 @@ public class ResettableMapCursor: MapCursor: ResettableCursorType { self.loadingObservable = loadingObservable } - public required init(initialFrom other: SingleLoadCursor) { + public required init(resetFrom other: SingleLoadCursor) { self.loadingObservable = other.loadingObservable } diff --git a/Sources/Classes/Cursors/StaticCursor.swift b/Sources/Classes/Cursors/StaticCursor.swift index 144cba0c..fca71d1b 100644 --- a/Sources/Classes/Cursors/StaticCursor.swift +++ b/Sources/Classes/Cursors/StaticCursor.swift @@ -34,7 +34,7 @@ public class StaticCursor: ResettableCursorType { self.content = content } - public required init(initialFrom other: StaticCursor) { + public required init(resetFrom other: StaticCursor) { self.content = other.content } diff --git a/Sources/Protocols/ResettableType.swift b/Sources/Protocols/ResettableType.swift index c100df98..223ae00a 100644 --- a/Sources/Protocols/ResettableType.swift +++ b/Sources/Protocols/ResettableType.swift @@ -28,7 +28,7 @@ public protocol ResettableType { /// Initializer with other instance parameter. /// /// - Parameter other: Other instance of specific type. - init(initialFrom other: Self) + init(resetFrom other: Self) } @@ -38,7 +38,7 @@ public extension ResettableType { /// /// - Returns: resseted instance of self func reset() -> Self { - return Self(initialFrom: self) + return Self(resetFrom: self) } } diff --git a/Tests/Cursors/StubCursor.swift b/Tests/Cursors/StubCursor.swift index 28210ff1..90b30cb8 100644 --- a/Tests/Cursors/StubCursor.swift +++ b/Tests/Cursors/StubCursor.swift @@ -50,7 +50,7 @@ class StubCursor: ResettableCursorType { self.requestDelay = requestDelay } - required init(initialFrom other: StubCursor) { + required init(resetFrom other: StubCursor) { self.maxItemsCount = other.maxItemsCount self.requestDelay = other.requestDelay } From e46f2f860e94bb4318e72b0a1cf9af397998a507 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 14:08:28 +0300 Subject: [PATCH 20/24] Fix podspec --- LeadKit.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LeadKit.podspec b/LeadKit.podspec index 5dabb07d..b322e718 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| ss.watchos.exclude_files = [ "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Classes/Views/AnyBaseTableRow/*", - "Sources/Classes/Views/BaseCell/*", + "Sources/Classes/Views/SeparatorCell/*", "Sources/Classes/Views/EmptyCell/*", "Sources/Classes/Views/XibView/*", "Sources/Classes/Views/SpinnerView/*", @@ -73,7 +73,7 @@ Pod::Spec.new do |s| ] ss.tvos.exclude_files = [ "Sources/Classes/Views/AnyBaseTableRow/*", - "Sources/Classes/Views/BaseCell/*", + "Sources/Classes/Views/SeparatorCell/*", "Sources/Classes/Views/EmptyCell/*", "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Structures/Drawing/CALayerDrawingOperation.swift", @@ -101,7 +101,7 @@ Pod::Spec.new do |s| ss.exclude_files = [ "Sources/Classes/Views/AnyBaseTableRow/*", - "Sources/Classes/Views/BaseCell/*", + "Sources/Classes/Views/SeparatorCell/*", "Sources/Classes/Views/EmptyCell/*", "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", From 84d9953ac027a9e9ac72287015ef1741858d46fe Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 14:34:34 +0300 Subject: [PATCH 21/24] Fix podspec --- LeadKit.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LeadKit.podspec b/LeadKit.podspec index b322e718..c3c8e6fa 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -106,7 +106,7 @@ Pod::Spec.new do |s| "Sources/Classes/Pagination/PaginationTableViewWrapper.swift", "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", - "Sources/Extensions/TableDirector/TableDirector+Extensions.swift", + "Sources/Extensions/TableDirector/*", "Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift" ] From a5a6148bf178036b64742c6c5376f3726bd4de62 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 17:25:06 +0300 Subject: [PATCH 22/24] Update seleciton style --- Sources/Classes/Views/EmptyCell/EmptyCell.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/Classes/Views/EmptyCell/EmptyCell.swift b/Sources/Classes/Views/EmptyCell/EmptyCell.swift index be80560e..b140c792 100644 --- a/Sources/Classes/Views/EmptyCell/EmptyCell.swift +++ b/Sources/Classes/Views/EmptyCell/EmptyCell.swift @@ -30,6 +30,7 @@ public final class EmptyCell: SeparatorCell, ConfigurableCell { public func configure(with viewModel: EmptyCellViewModel) { backgroundColor = .clear contentView.backgroundColor = viewModel.color + selectionStyle = .none configureSeparator(with: viewModel) } From 827d8a3ca2bed71af0fcc2cd6d50434afbf56292 Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 23:56:39 +0300 Subject: [PATCH 23/24] Update for review --- LeadKit.podspec | 6 +++--- LeadKit.xcodeproj/project.pbxproj | 12 ++++++------ .../Views/SeparatorCell/SeparatorCellViewModel.swift | 5 +++++ ...s.swift => Array+AnyBaseTableRowExtensions.swift} | 0 .../TableDirector/TableRow+Extensions.swift | 7 ++++++- 5 files changed, 20 insertions(+), 10 deletions(-) rename Sources/Extensions/Array/{Array+AnyBaseTableRow+Extensions.swift => Array+AnyBaseTableRowExtensions.swift} (100%) diff --git a/LeadKit.podspec b/LeadKit.podspec index c3c8e6fa..d282fe81 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -54,7 +54,7 @@ Pod::Spec.new do |s| "Sources/Extensions/StoryboardProtocol/*", "Sources/Extensions/Support/UIScrollView+Support.swift", "Sources/Extensions/TableDirector/*", - "Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift", + "Sources/Extensions/Array/Array+AnyBaseTableRowExtensions.swift", "Sources/Extensions/UIActivityIndicatorView/*", "Sources/Extensions/UIAlertcontroller/*", "Sources/Extensions/UICollectionView/*", @@ -81,7 +81,7 @@ Pod::Spec.new do |s| "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", "Sources/Extensions/Support/UIScrollView+Support.swift", "Sources/Extensions/TableDirector/*", - "Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift" + "Sources/Extensions/Array/Array+AnyBaseTableRowExtensions.swift" ] ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0' @@ -107,7 +107,7 @@ Pod::Spec.new do |s| "Sources/Extensions/NetworkService/NetworkService+ActivityIndicator.swift", "Sources/Extensions/PaginationTableViewWrapperDelegate/PaginationTableViewWrapperDelegate+DefaultImplementation.swift", "Sources/Extensions/TableDirector/*", - "Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift" + "Sources/Extensions/Array/Array+AnyBaseTableRowExtensions.swift" ] ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0' diff --git a/LeadKit.xcodeproj/project.pbxproj b/LeadKit.xcodeproj/project.pbxproj index fd941c61..ed16ed59 100644 --- a/LeadKit.xcodeproj/project.pbxproj +++ b/LeadKit.xcodeproj/project.pbxproj @@ -386,8 +386,8 @@ 82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; }; A658E54D1F8CD7790093527A /* TableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */; }; A658E54E1F8CD7790093527A /* TableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */; }; - A658E5501F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */; }; - A658E5511F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */; }; + A658E5501F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift */; }; + A658E5511F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift */; }; A6C9A4FA1F8BBCF2009311CC /* EmptyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */; }; A6C9A4FB1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */; }; A6C9A5041F8BC78F009311CC /* CellSeparatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */; }; @@ -601,7 +601,7 @@ 95E457F1241D136396FC2420 /* Pods_LeadKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9966FB938D114F79F71AE037 /* Pods-LeadKit-LeadKit iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit-LeadKit iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit-LeadKit iOS/Pods-LeadKit-LeadKit iOS.release.xcconfig"; sourceTree = ""; }; A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TableRow+Extensions.swift"; sourceTree = ""; }; - A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+AnyBaseTableRow+Extensions.swift"; sourceTree = ""; }; + A658E54F1F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+AnyBaseTableRowExtensions.swift"; sourceTree = ""; }; A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCellViewModel.swift; sourceTree = ""; }; A66428A61F8A653600C6308D /* SeparatorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCell.swift; sourceTree = ""; }; A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = ""; }; @@ -1368,7 +1368,7 @@ isa = PBXGroup; children = ( EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */, - A658E54F1F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift */, + A658E54F1F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift */, ); path = Array; sourceTree = ""; @@ -2154,7 +2154,7 @@ 671463041EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */, EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */, 671463701EB3396E00EAB194 /* ApiRequestParameters.swift in Sources */, - A658E5501F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */, + A658E5501F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift in Sources */, 671462EC1EB3396E00EAB194 /* UIImage+Extensions.swift in Sources */, A6E0DDF11F8A6C80002CA74E /* SeparatorConfiguration.swift in Sources */, 6714636C1EB3396E00EAB194 /* XibNameProtocol.swift in Sources */, @@ -2220,7 +2220,7 @@ 671463B81EB34B1E00EAB194 /* StubCursor.swift in Sources */, A658E54E1F8CD7790093527A /* TableRow+Extensions.swift in Sources */, A6E0DDE41F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */, - A658E5511F8CD9350093527A /* Array+AnyBaseTableRow+Extensions.swift in Sources */, + A658E5511F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift in Sources */, 671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */, A6F32C101F6EBE9600AC08EE /* StringExtensionTests.swift in Sources */, 671463C11EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */, diff --git a/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift index ded62dcd..a109f002 100644 --- a/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift @@ -41,6 +41,11 @@ open class SeparatorCellViewModel { public extension SeparatorCellViewModel { + func with(separatorType: CellSeparatorType) -> Self { + set(separatorType: separatorType) + return self + } + func set(separatorType: CellSeparatorType) { self.separatorType = separatorType diff --git a/Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift b/Sources/Extensions/Array/Array+AnyBaseTableRowExtensions.swift similarity index 100% rename from Sources/Extensions/Array/Array+AnyBaseTableRow+Extensions.swift rename to Sources/Extensions/Array/Array+AnyBaseTableRowExtensions.swift diff --git a/Sources/Extensions/TableDirector/TableRow+Extensions.swift b/Sources/Extensions/TableDirector/TableRow+Extensions.swift index 35c157d2..3ee4f421 100644 --- a/Sources/Extensions/TableDirector/TableRow+Extensions.swift +++ b/Sources/Extensions/TableDirector/TableRow+Extensions.swift @@ -24,7 +24,12 @@ import TableKit public extension TableRow where CellType.T: SeparatorCellViewModel { - func with(separatorType: CellSeparatorType) { + func with(separatorType: CellSeparatorType) -> Self { + item.set(separatorType: separatorType) + return self + } + + func set(separatorType: CellSeparatorType) { item.set(separatorType: separatorType) } From dca12659d1a73e9ba1e4dedd13ade1f97d062e4a Mon Sep 17 00:00:00 2001 From: Igor Date: Tue, 10 Oct 2017 23:59:13 +0300 Subject: [PATCH 24/24] Few clarifications --- .../Views/SeparatorCell/SeparatorCell.swift | 20 +++++++++---------- .../SeparatorCellViewModel.swift | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift index 2b9d0d60..918713e1 100644 --- a/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCell.swift @@ -42,16 +42,16 @@ open class SeparatorCell: UITableViewCell { configureInterface(with: viewModel) } - /// Use this function to place separator at hierarchy - /// - parameter front: Move separator to front or bottom in heirarchy - public func moveSeparators(to front: Bool) { - if front { - contentView.bringSubview(toFront: topView) - contentView.bringSubview(toFront: bottomView) - } else { - contentView.sendSubview(toBack: topView) - contentView.sendSubview(toBack: bottomView) - } + /// Move separator upward in hierarchy + public func bringSeparatorsToFront() { + contentView.bringSubview(toFront: topView) + contentView.bringSubview(toFront: bottomView) + } + + /// Move separator backward in hierarchy + public func sendSeparatorsToBack() { + contentView.sendSubview(toBack: topView) + contentView.sendSubview(toBack: bottomView) } // MARK: - Private diff --git a/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift index a109f002..1fac48ec 100644 --- a/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift +++ b/Sources/Classes/Views/SeparatorCell/SeparatorCellViewModel.swift @@ -28,11 +28,11 @@ open class SeparatorCellViewModel { internal var separatorType = CellSeparatorType.none /// Configuration for topSeparator - /// - Importnat: Bottom dimension is ignored + /// - Important: Bottom dimension is ignored internal var topSeparatorConfiguration: SeparatorConfiguration? /// Configuration for topSeparator - /// - Importnat: Top dimension is ignored + /// - Important: Top dimension is ignored internal var bottomSeparatorConfiguration: SeparatorConfiguration? public init() {}