Merge pull request #91 from TouchInstinct/feature/base-cell

Feature. Base cell
This commit is contained in:
Igor Kislyuk 2017-10-11 13:03:07 +03:00 committed by GitHub
commit 763efd8968
23 changed files with 823 additions and 17 deletions

View File

@ -18,4 +18,11 @@
## 0.5.10
- **Fix**: `Public` modifier for `SpinnerView`
- **Fix**: `Public` modifier for `SpinnerView`
## 0.5.11
- **[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

View File

@ -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"
@ -41,8 +41,11 @@ 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/AnyBaseTableRow/*",
"Sources/Classes/Views/SeparatorCell/*",
"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",
@ -50,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/Extensions/Array/Array+AnyBaseTableRowExtensions.swift",
"Sources/Extensions/UIActivityIndicatorView/*",
"Sources/Extensions/UIAlertcontroller/*",
"Sources/Extensions/UICollectionView/*",
@ -68,12 +72,16 @@ Pod::Spec.new do |s|
"Sources/Structures/DrawingOperations/BorderDrawingOperation.swift",
]
ss.tvos.exclude_files = [
"Sources/Classes/Views/AnyBaseTableRow/*",
"Sources/Classes/Views/SeparatorCell/*",
"Sources/Classes/Views/EmptyCell/*",
"Sources/Classes/Pagination/PaginationTableViewWrapper.swift",
"Sources/Structures/Drawing/CALayerDrawingOperation.swift",
"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/Extensions/Array/Array+AnyBaseTableRowExtensions.swift"
]
ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0'
@ -92,10 +100,14 @@ Pod::Spec.new do |s|
ss.source_files = "Sources/**/*.swift"
ss.exclude_files = [
"Sources/Classes/Views/AnyBaseTableRow/*",
"Sources/Classes/Views/SeparatorCell/*",
"Sources/Classes/Views/EmptyCell/*",
"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+AnyBaseTableRowExtensions.swift"
]
ss.dependency "CocoaLumberjack/Swift", '~> 3.1.0'

View File

@ -384,6 +384,30 @@
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 */; };
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 */; };
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 /* 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 /* 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 */; };
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 +600,17 @@
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 = "<group>"; };
A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TableRow+Extensions.swift"; sourceTree = "<group>"; };
A658E54F1F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+AnyBaseTableRowExtensions.swift"; sourceTree = "<group>"; };
A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCellViewModel.swift; sourceTree = "<group>"; };
A66428A61F8A653600C6308D /* SeparatorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorCell.swift; sourceTree = "<group>"; };
A66428A71F8A654600C6308D /* EmptyCellRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellRow.swift; sourceTree = "<group>"; };
A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyBaseTableRow.swift; sourceTree = "<group>"; };
A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCellViewModel.swift; sourceTree = "<group>"; };
A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyCell.swift; sourceTree = "<group>"; };
A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Comparable+Extensions.swift"; sourceTree = "<group>"; };
A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellSeparatorType.swift; sourceTree = "<group>"; };
A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeparatorConfiguration.swift; sourceTree = "<group>"; };
A6F32C071F6EBDAA00AC08EE /* String+LocalizedComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+LocalizedComponent.swift"; sourceTree = "<group>"; };
A6F32C0E1F6EBE8E00AC08EE /* StringExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionTests.swift; sourceTree = "<group>"; };
A854A36EB179651E6D0CC9FB /* Pods_LeadKit_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -718,8 +753,11 @@
671461D41EB3396E00EAB194 /* Views */ = {
isa = PBXGroup;
children = (
67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */,
671461D51EB3396E00EAB194 /* XibView.swift */,
A6AF3B381F8B957400CDB971 /* AnyBaseTableRow */,
A66428A41F8A651700C6308D /* SeparatorCell */,
A6C9A4F71F8BBC0F009311CC /* EmptyCell */,
A6C9A4F81F8BBC27009311CC /* SpinnerView */,
A6C9A4F91F8BBCCE009311CC /* XibView */,
);
path = Views;
sourceTree = "<group>";
@ -737,6 +775,7 @@
671461DA1EB3396E00EAB194 /* Extensions */ = {
isa = PBXGroup;
children = (
A6D10EA91F8A9269003E69DD /* Comparable */,
671461DB1EB3396E00EAB194 /* Alamofire */,
EFBE57CE1EC35ED90040E00A /* Array */,
67A1FF921EBCA64A00D6C89F /* CABasicAnimation */,
@ -906,6 +945,7 @@
isa = PBXGroup;
children = (
671462011EB3396E00EAB194 /* TableDirector+Extensions.swift */,
A658E54C1F8CD7790093527A /* TableRow+Extensions.swift */,
);
path = TableDirector;
sourceTree = "<group>";
@ -1222,12 +1262,64 @@
path = Single;
sourceTree = "<group>";
};
A66428A41F8A651700C6308D /* SeparatorCell */ = {
isa = PBXGroup;
children = (
A66428A61F8A653600C6308D /* SeparatorCell.swift */,
A66428A51F8A653500C6308D /* SeparatorCellViewModel.swift */,
A6E0DDEE1F8A6C57002CA74E /* CellSeparatorType.swift */,
A6E0DDF01F8A6C80002CA74E /* SeparatorConfiguration.swift */,
);
path = SeparatorCell;
sourceTree = "<group>";
};
A6AF3B381F8B957400CDB971 /* AnyBaseTableRow */ = {
isa = PBXGroup;
children = (
A66428A81F8A655600C6308D /* AnyBaseTableRow.swift */,
);
path = AnyBaseTableRow;
sourceTree = "<group>";
};
A6C9A4F71F8BBC0F009311CC /* EmptyCell */ = {
isa = PBXGroup;
children = (
A6AF3B371F8B956F00CDB971 /* EmptyCell.swift */,
A6AF3B361F8B956E00CDB971 /* EmptyCellViewModel.swift */,
A66428A71F8A654600C6308D /* EmptyCellRow.swift */,
);
path = EmptyCell;
sourceTree = "<group>";
};
A6C9A4F81F8BBC27009311CC /* SpinnerView */ = {
isa = PBXGroup;
children = (
67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */,
);
path = SpinnerView;
sourceTree = "<group>";
};
A6C9A4F91F8BBCCE009311CC /* XibView */ = {
isa = PBXGroup;
children = (
671461D51EB3396E00EAB194 /* XibView.swift */,
);
path = XibView;
sourceTree = "<group>";
};
A6D10EA91F8A9269003E69DD /* Comparable */ = {
isa = PBXGroup;
children = (
A6D10EAA1F8A9278003E69DD /* Comparable+Extensions.swift */,
);
path = Comparable;
sourceTree = "<group>";
};
A6F32C0D1F6EBE7700AC08EE /* Extensions */ = {
isa = PBXGroup;
children = (
A6F32C0E1F6EBE8E00AC08EE /* StringExtensionTests.swift */,
);
name = Extensions;
path = Extensions;
sourceTree = "<group>";
};
@ -1276,6 +1368,7 @@
isa = PBXGroup;
children = (
EFBE57CF1EC35EF20040E00A /* Array+Extensions.swift */,
A658E54F1F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift */,
);
path = Array;
sourceTree = "<group>";
@ -2011,6 +2104,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 */,
@ -2028,6 +2122,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 */,
@ -2036,12 +2131,15 @@
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 */,
671463801EB3396E00EAB194 /* PaddingDrawingOperation.swift in Sources */,
671462E01EB3396E00EAB194 /* UICollectionView+CellRegistration.swift in Sources */,
671462601EB3396E00EAB194 /* PaginationTableViewWrapper.swift in Sources */,
671463281EB3396E00EAB194 /* BaseViewModel.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 */,
@ -2050,10 +2148,15 @@
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 */,
A6C9A4FB1F8BBCF2009311CC /* EmptyCellViewModel.swift in Sources */,
671463041EB3396E00EAB194 /* UIView+LoadingIndicator.swift in Sources */,
EFBE57D61EC3603E0040E00A /* UIAlertController+Extensions.swift in Sources */,
671463701EB3396E00EAB194 /* ApiRequestParameters.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 */,
6771DFEA1EEA7CB8002DCDAE /* DateFormattingService+MappingTransform.swift in Sources */,
671462A41EB3396E00EAB194 /* IndexPath+ImmutableIndexPath.swift in Sources */,
@ -2075,6 +2178,7 @@
A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */,
671462881EB3396E00EAB194 /* CGFloat+Pixels.swift in Sources */,
671462941EB3396E00EAB194 /* CGSize+CGContextSize.swift in Sources */,
A6E0DDE01F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */,
671463641EB3396E00EAB194 /* ViewHeightProtocol.swift in Sources */,
671462481EB3396E00EAB194 /* FixedPageCursor.swift in Sources */,
671462C81EB3396E00EAB194 /* String+Localization.swift in Sources */,
@ -2107,14 +2211,25 @@
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 */,
A658E54E1F8CD7790093527A /* TableRow+Extensions.swift in Sources */,
A6E0DDE41F8A696F002CA74E /* SeparatorCellViewModel.swift in Sources */,
A658E5511F8CD9350093527A /* Array+AnyBaseTableRowExtensions.swift in Sources */,
671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */,
A6F32C101F6EBE9600AC08EE /* StringExtensionTests.swift in Sources */,
671463C11EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */,
671463BE1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */,
A6E0DDE31F8A696F002CA74E /* SeparatorCell.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;
};
@ -2382,6 +2497,7 @@
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 */,
@ -2418,6 +2534,7 @@
buildActionMask = 2147483647;
files = (
671463C21EB34B1E00EAB194 /* MappableUserDefaultsTests.swift in Sources */,
A6C9A5111F8BC79D009311CC /* Comparable+Extensions.swift in Sources */,
671463BF1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */,
671463C51EB34B1E00EAB194 /* Post.swift in Sources */,
671463CB1EB34B1E00EAB194 /* TestView.swift in Sources */,

View File

@ -80,7 +80,7 @@ public class ResettableFixedPageCursor<Cursor: ResettableCursorType>: 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)
}

View File

@ -95,7 +95,7 @@ public class ResettableMapCursor<Cursor: ResettableCursorType, T>: MapCursor<Cur
super.init(cursor: cursor, transform: transform)
}
public required init(initialFrom other: ResettableMapCursor) {
public required init(resetFrom other: ResettableMapCursor) {
super.init(cursor: other.cursor.reset(), transform: other.transform)
}

View File

@ -36,7 +36,7 @@ public class SingleLoadCursor<Element>: ResettableCursorType {
self.loadingObservable = loadingObservable
}
public required init(initialFrom other: SingleLoadCursor) {
public required init(resetFrom other: SingleLoadCursor) {
self.loadingObservable = other.loadingObservable
}

View File

@ -34,7 +34,7 @@ public class StaticCursor<Element>: ResettableCursorType {
self.content = content
}
public required init(initialFrom other: StaticCursor) {
public required init(resetFrom other: StaticCursor) {
self.content = other.content
}

View File

@ -0,0 +1,65 @@
//
// 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<T>
private class AnyBaseTableRowHolder {
let row: Row
init(tableRow: Row) {
row = tableRow
}
}
/// Class used to hold resolved TableRow
private final class AnyBaseTableRowBox<T: ConfigurableCell>: AnyBaseTableRowHolder
where T: SeparatorCell, T.T: SeparatorCellViewModel {
init(tableRow: TableRow<T>) {
super.init(tableRow: tableRow)
}
}
/// Class that used to configure separators when multiply cells presented in one section
/// Holds TableRow<T> with any model inherited from BaseCellViewModel
public final class AnyBaseTableRow {
private let anyTableRow: AnyBaseTableRowHolder
/// Row `item`, that typed as BaseCellViewModel
public let viewModel: SeparatorCellViewModel
/// 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<T>(tableRow: TableRow<T>) where T: SeparatorCell, T.T: SeparatorCellViewModel {
anyTableRow = AnyBaseTableRowBox(tableRow: tableRow)
viewModel = tableRow.item
}
}

View File

@ -0,0 +1,38 @@
//
// 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
/// Empty cell class. Do not use it directly.
/// - see: `EmptyCellRow`
public final class EmptyCell: SeparatorCell, ConfigurableCell {
public func configure(with viewModel: EmptyCellViewModel) {
backgroundColor = .clear
contentView.backgroundColor = viewModel.color
selectionStyle = .none
configureSeparator(with: viewModel)
}
}

View File

@ -0,0 +1,58 @@
//
// 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 that
/// - Simulates spacing with no-breaking constraints
/// - Can end editing on click
public final class EmptyCellRow: TableRow<EmptyCell> {
/// 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) {
self.init(item: EmptyCellViewModel(height: height, color: color))
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 public var defaultHeight: CGFloat? {
return item.height
}
/// EmptyCellRow typed as AnyBaseTableRow
public var anyRow: AnyBaseTableRow {
return AnyBaseTableRow(tableRow: self)
}
}

View File

@ -0,0 +1,39 @@
//
// 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
/// ViewModel for EmptyCell
public final class EmptyCellViewModel: SeparatorCellViewModel {
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
}
}

View File

@ -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 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)
/// First configuration for top, second for bottom
case full(SeparatorConfiguration, SeparatorConfiguration)
}
public extension CellSeparatorType {
/// Determine if bottom separator is hidden
var bottomIsHidden: Bool {
switch self {
case .top, .none:
return true
case .bottom, .full:
return false
}
}
/// Determine if top separator is hidden
var topIsHidden: Bool {
switch self {
case .bottom, .none:
return true
case .top, .full:
return false
}
}
}

View File

@ -0,0 +1,168 @@
//
// 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
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:)`
/// - 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
/// Configure separator with viewModel
/// - parameter viewModel: ViewModel of cell, that inherits from BaseCellViewModel
public func configureSeparator(with viewModel: SeparatorCellViewModel) {
configureInterface(with: viewModel)
}
/// 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
private var topView: UIView!
private var bottomView: UIView!
// top separator constraints
private var topViewLeftConstraint: NSLayoutConstraint!
private var topViewRightConstraint: NSLayoutConstraint!
private var topViewTopConstraint: NSLayoutConstraint!
private var topViewHeightConstraint: NSLayoutConstraint!
// bottom separator constraints
private var bottomViewLeftConstraint: NSLayoutConstraint!
private var bottomViewRightConstraint: NSLayoutConstraint!
private var bottomViewBottomConstraint: NSLayoutConstraint!
private var bottomViewHeightConstraint: NSLayoutConstraint!
private var topSeparatorInsets = UIEdgeInsets.zero
private var bottomSeparatorInsets = UIEdgeInsets.zero
private var topSeparatorHeight = Constants.defaultSeparatorHeight
private var bottomSeparatorHeight = Constants.defaultSeparatorHeight
// MARK: - Initialization
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()
}
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()
}
// 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 ?? Constants.defaultSeparatorHeight
topSeparatorInsets = viewModel.topSeparatorConfiguration?.insets ?? .zero
bottomView.backgroundColor = viewModel.bottomSeparatorConfiguration?.color
bottomSeparatorHeight = viewModel.bottomSeparatorConfiguration?.height ?? Constants.defaultSeparatorHeight
bottomSeparatorInsets = viewModel.bottomSeparatorConfiguration?.insets ?? .zero
}
private func configureLineViews() {
topView = createSeparatorView()
bottomView = createSeparatorView()
createConstraints()
}
private func createSeparatorView() -> UIView {
let view = UIView()
view.isHidden = true
view.backgroundColor = .black
view.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(view)
return view
}
private func createConstraints() {
// height
topViewHeightConstraint = topView.heightAnchor.constraint(equalToConstant: topSeparatorHeight)
topViewHeightConstraint.isActive = true
bottomViewHeightConstraint = bottomView.heightAnchor.constraint(equalToConstant: bottomSeparatorHeight)
bottomViewHeightConstraint.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
}
}

View File

@ -0,0 +1,68 @@
//
// 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
/// By default this class does not provide any separators
open class SeparatorCellViewModel {
internal var separatorType = CellSeparatorType.none
/// Configuration for topSeparator
/// - Important: Bottom dimension is ignored
internal var topSeparatorConfiguration: SeparatorConfiguration?
/// Configuration for topSeparator
/// - Important: Top dimension is ignored
internal var bottomSeparatorConfiguration: SeparatorConfiguration?
public init() {}
}
public extension SeparatorCellViewModel {
func with(separatorType: CellSeparatorType) -> Self {
set(separatorType: separatorType)
return self
}
func set(separatorType: CellSeparatorType) {
self.separatorType = separatorType
switch separatorType {
case .top(let configuration):
topSeparatorConfiguration = configuration
bottomSeparatorConfiguration = nil
case .bottom(let configuration):
topSeparatorConfiguration = nil
bottomSeparatorConfiguration = configuration
case .full(let top, let bottom):
topSeparatorConfiguration = top
bottomSeparatorConfiguration = bottom
case .none:
topSeparatorConfiguration = nil
bottomSeparatorConfiguration = nil
}
}
}

View File

@ -0,0 +1,42 @@
//
// 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
/// 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
}
}

View File

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

View File

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

View File

@ -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.set(separatorType: .full(extremeSeparatorConfiguration, extremeSeparatorConfiguration))
default:
rows.forEach { $0.viewModel.set(separatorType: .full(middleSeparatorConfiguration, middleSeparatorConfiguration))}
rows.first?.viewModel.set(separatorType: .top(extremeSeparatorConfiguration))
rows.last?.viewModel.set(separatorType: .bottom(extremeSeparatorConfiguration))
}
}
}

View File

@ -0,0 +1,36 @@
//
// 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 {
func with(separatorType: CellSeparatorType) -> Self {
item.set(separatorType: separatorType)
return self
}
func set(separatorType: CellSeparatorType) {
item.set(separatorType: separatorType)
}
}

View File

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

View File

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