Merge branch 'master' into feature/request_network_operation_state

# Conflicts:
#	CHANGELOG.md
#	LeadKit.podspec
#	LeadKit.xcodeproj/project.pbxproj
This commit is contained in:
Ivan Smolin 2018-05-22 17:17:13 +03:00
commit 609e1a9ff4
15 changed files with 354 additions and 192 deletions

View File

@ -1,8 +1,21 @@
# Changelog
### 0.7.14
### 0.7.17
- **Add**: `RxNetworkOperationModel` base class, `NetworkOperationState` and `NetworkOperationStateType` protocols.
### 0.7.16
- **[Breaking Change]**: Remove `ModuleConfigurator`, change type of `ConfigurableController.viewModel` property from `IUO` to plain `ViewModelT`.
- **Add**: `InitializableView` protocol with default implementation.
- **Update**: `ConfigurableController` protocol now inherit `InitializableView`.
- **[Breaking Change]**: `setAppearance` of `ConfigurableController` replaced with `configureAppearance` of `InitializableView`.
### 0.7.15
- **Fix**: `Double.roundValue(withPrecision:)` rounding issue
- **Add**: `Double+Rounding` test case
### 0.7.14
- **[Breaking Change]**: `PaginationWrapper` separating state views from data loading.
### 0.7.13
- **Update**: Migrate from `Variable` to `BehaviorRelay`.
- **Fix**: `PaginationWrapper` retry load more after fail.
@ -25,7 +38,7 @@
- **Remove**: `App`, `Log` and `LogFormatter`.
- **Remove**: `CocoaLumberjack` dependency.
- **Add**: Rotate operation for image drawing.
- **Add**: `mapViewEvents` overload with closure that returns array of disposables.
- **Add**: `mapViewEvents` overload with closure that returns array of disposables.
- **Update**: Update `ObjectMapper` to 3.1.
- **Add**: `apiRequestParameters` method to `NetworkServiceConfiguration` extension.
- **Update**: Rename setToCenter(withInsets:) to pintToSuperview(withInsets:excluding:)

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "LeadKit"
s.version = "0.7.14"
s.version = "0.7.17"
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"

View File

@ -171,10 +171,6 @@
6714633C1EB3396E00EAB194 /* LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462281EB3396E00EAB194 /* LoadingIndicator.swift */; };
6714633D1EB3396E00EAB194 /* LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462281EB3396E00EAB194 /* LoadingIndicator.swift */; };
6714633F1EB3396E00EAB194 /* LoadingIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462281EB3396E00EAB194 /* LoadingIndicator.swift */; };
671463401EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462291EB3396E00EAB194 /* ModuleConfigurator.swift */; };
671463411EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462291EB3396E00EAB194 /* ModuleConfigurator.swift */; };
671463421EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462291EB3396E00EAB194 /* ModuleConfigurator.swift */; };
671463431EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 671462291EB3396E00EAB194 /* ModuleConfigurator.swift */; };
671463481EB3396E00EAB194 /* ResettableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6714622B1EB3396E00EAB194 /* ResettableType.swift */; };
671463491EB3396E00EAB194 /* ResettableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6714622B1EB3396E00EAB194 /* ResettableType.swift */; };
6714634A1EB3396E00EAB194 /* ResettableType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6714622B1EB3396E00EAB194 /* ResettableType.swift */; };
@ -375,7 +371,7 @@
6774526C206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */; };
6774526D206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */; };
6774526E206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */; };
6774527020624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526F20624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift */; };
6774527020624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526F20624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift */; };
6774527420624E820024EEEF /* DataLoadingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774527320624E820024EEEF /* DataLoadingModel.swift */; };
6774527520624E820024EEEF /* DataLoadingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774527320624E820024EEEF /* DataLoadingModel.swift */; };
6774527620624E820024EEEF /* DataLoadingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774527320624E820024EEEF /* DataLoadingModel.swift */; };
@ -505,8 +501,14 @@
67EB7FFE206176C900BDD9FB /* AnyPaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB7FFC206176C900BDD9FB /* AnyPaginationWrappable.swift */; };
67EB7FFF206176C900BDD9FB /* AnyPaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB7FFC206176C900BDD9FB /* AnyPaginationWrappable.swift */; };
67EB8001206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */; };
67EB8002206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */; };
67EB8003206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */; };
67ED2BDE20B44DEB00508B3E /* InitializableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BDD20B44DEB00508B3E /* InitializableView.swift */; };
67ED2BDF20B44DEB00508B3E /* InitializableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BDD20B44DEB00508B3E /* InitializableView.swift */; };
67ED2BE020B44DEB00508B3E /* InitializableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BDD20B44DEB00508B3E /* InitializableView.swift */; };
67ED2BE120B44DEB00508B3E /* InitializableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BDD20B44DEB00508B3E /* InitializableView.swift */; };
67ED2BE520B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BE420B44F4300508B3E /* InitializableView+DefaultImplementation.swift */; };
67ED2BE620B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BE420B44F4300508B3E /* InitializableView+DefaultImplementation.swift */; };
67ED2BE720B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BE420B44F4300508B3E /* InitializableView+DefaultImplementation.swift */; };
67ED2BE820B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BE420B44F4300508B3E /* InitializableView+DefaultImplementation.swift */; };
67FD4382206BD24B005B0C64 /* EqutableOptionalArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FD4381206BD24B005B0C64 /* EqutableOptionalArray.swift */; };
67FD4383206BD24B005B0C64 /* EqutableOptionalArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FD4381206BD24B005B0C64 /* EqutableOptionalArray.swift */; };
67FD4384206BD24B005B0C64 /* EqutableOptionalArray.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FD4381206BD24B005B0C64 /* EqutableOptionalArray.swift */; };
@ -515,11 +517,11 @@
67FDC2601FA310EA00C76A77 /* RequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FDC25E1FA310EA00C76A77 /* RequestError.swift */; };
67FDC2611FA310EA00C76A77 /* RequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FDC25E1FA310EA00C76A77 /* RequestError.swift */; };
67FDC2621FA310EA00C76A77 /* RequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FDC25E1FA310EA00C76A77 /* RequestError.swift */; };
820CAD8420B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 820CAD8320B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift */; };
825F8F2820B3384C00594857 /* PaginationWrapperUIDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 825F8F2720B3384C00594857 /* PaginationWrapperUIDelegate.swift */; };
82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; };
A658E54D1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift */; };
A658E54E1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift */; };
A658E5501F8CD9350093527A /* Array+SeparatorRowBoxExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+SeparatorRowBoxExtensions.swift */; };
A658E5511F8CD9350093527A /* Array+SeparatorRowBoxExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54F1F8CD9350093527A /* Array+SeparatorRowBoxExtensions.swift */; };
A676AE481F97D28A001F9214 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A676AE471F97D28A001F9214 /* String+Extensions.swift */; };
A676AE491F97D28A001F9214 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A676AE471F97D28A001F9214 /* String+Extensions.swift */; };
A676AE4A1F97D28A001F9214 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A676AE471F97D28A001F9214 /* String+Extensions.swift */; };
@ -541,8 +543,6 @@
A6E0DDDE1F8A696F002CA74E /* EmptyCellRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A71F8A654600C6308D /* EmptyCellRow.swift */; };
A6E0DDDF1F8A696F002CA74E /* SeparatorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* SeparatorCell.swift */; };
A6E0DDE11F8A696F002CA74E /* SeparatorRowBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* SeparatorRowBox.swift */; };
A6E0DDE31F8A696F002CA74E /* SeparatorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A61F8A653600C6308D /* SeparatorCell.swift */; };
A6E0DDE51F8A696F002CA74E /* SeparatorRowBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = A66428A81F8A655600C6308D /* SeparatorRowBox.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 */; };
@ -553,6 +553,9 @@
A6F32C121F6EBE9800AC08EE /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6F32C0E1F6EBE8E00AC08EE /* StringExtensionTests.swift */; };
BA6C6DB45950382041948FC5 /* Pods_LeadKit_LeadKit_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFE9323150A9760008093F73 /* Pods_LeadKit_LeadKit_iOS.framework */; };
D6EE55093E404DEA62B03DDF /* Pods_LeadKit_LeadKit_watchOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8590CA7831555C295C5DC572 /* Pods_LeadKit_LeadKit_watchOS.framework */; };
D93221EE20A44896003799D5 /* Double+RoundingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93221ED20A44896003799D5 /* Double+RoundingTests.swift */; };
D93221EF20A44896003799D5 /* Double+RoundingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93221ED20A44896003799D5 /* Double+RoundingTests.swift */; };
D93221F020A44896003799D5 /* Double+RoundingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93221ED20A44896003799D5 /* Double+RoundingTests.swift */; };
DEE25FE98D40ED1C168F384A /* Pods_LeadKit_LeadKit_iOS_Extensions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 887F99C5326BD220C2811BD6 /* Pods_LeadKit_LeadKit_iOS_Extensions.framework */; };
EF24213A2076D5BD00FA9BE6 /* NetworkServiceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF2421392076D5BD00FA9BE6 /* NetworkServiceConfiguration.swift */; };
EF24213B2076D5C700FA9BE6 /* NetworkServiceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = EF2421392076D5BD00FA9BE6 /* NetworkServiceConfiguration.swift */; };
@ -670,7 +673,6 @@
671462251EB3396E00EAB194 /* CursorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CursorType.swift; sourceTree = "<group>"; };
671462261EB3396E00EAB194 /* DrawingOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DrawingOperation.swift; sourceTree = "<group>"; };
671462281EB3396E00EAB194 /* LoadingIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingIndicator.swift; sourceTree = "<group>"; };
671462291EB3396E00EAB194 /* ModuleConfigurator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModuleConfigurator.swift; sourceTree = "<group>"; };
6714622B1EB3396E00EAB194 /* ResettableType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResettableType.swift; sourceTree = "<group>"; };
6714622C1EB3396E00EAB194 /* ReuseIdentifierProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReuseIdentifierProtocol.swift; sourceTree = "<group>"; };
6714622E1EB3396E00EAB194 /* StaticViewHeightProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StaticViewHeightProtocol.swift; sourceTree = "<group>"; };
@ -732,7 +734,7 @@
6771DFE91EEA7CB8002DCDAE /* DateFormattingService+MappingTransform.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DateFormattingService+MappingTransform.swift"; sourceTree = "<group>"; };
67745267206249360024EEEF /* UITableView+PaginationWrappable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+PaginationWrappable.swift"; sourceTree = "<group>"; };
6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionView+PaginationWrappable.swift"; sourceTree = "<group>"; };
6774526F20624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaginationWrapperDelegate+DefaultImplementation.swift"; sourceTree = "<group>"; };
6774526F20624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaginationWrapperUIDelegate+DefaultImplementation.swift"; sourceTree = "<group>"; };
6774527320624E820024EEEF /* DataLoadingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataLoadingModel.swift; sourceTree = "<group>"; };
67745278206252020024EEEF /* DataLoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataLoadingState.swift; sourceTree = "<group>"; };
6774527F206256A20024EEEF /* RxDataLoadingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RxDataLoadingModel.swift; sourceTree = "<group>"; };
@ -780,9 +782,13 @@
67EB7FF7206175F700BDD9FB /* PaginationWrappable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationWrappable.swift; sourceTree = "<group>"; };
67EB7FFC206176C900BDD9FB /* AnyPaginationWrappable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyPaginationWrappable.swift; sourceTree = "<group>"; };
67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationWrapperDelegate.swift; sourceTree = "<group>"; };
67ED2BDD20B44DEB00508B3E /* InitializableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InitializableView.swift; sourceTree = "<group>"; };
67ED2BE420B44F4300508B3E /* InitializableView+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "InitializableView+DefaultImplementation.swift"; sourceTree = "<group>"; };
67FD4381206BD24B005B0C64 /* EqutableOptionalArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EqutableOptionalArray.swift; sourceTree = "<group>"; };
67FDC25E1FA310EA00C76A77 /* RequestError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestError.swift; sourceTree = "<group>"; };
78405D3B3D3C3E17456877FF /* Pods_LeadKit_iOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_iOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
820CAD8320B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaginationWrapperDelegate+DefaultImplementation.swift"; sourceTree = "<group>"; };
825F8F2720B3384C00594857 /* PaginationWrapperUIDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationWrapperUIDelegate.swift; sourceTree = "<group>"; };
82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Single+DeferredJust.swift"; sourceTree = "<group>"; };
8590CA7831555C295C5DC572 /* Pods_LeadKit_LeadKit_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
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; };
@ -808,6 +814,7 @@
CFE9323150A9760008093F73 /* Pods_LeadKit_LeadKit_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D0F8D0002B21A4F31981F1ED /* Pods_LeadKit_LeadKit_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D840E55867DC9BB63460B856 /* Pods-LeadKit tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKit tvOSTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKit tvOSTests/Pods-LeadKit tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
D93221ED20A44896003799D5 /* Double+RoundingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+RoundingTests.swift"; sourceTree = "<group>"; };
DF1148A279C7AC7A42B0A0F8 /* Pods_LeadKit_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EF2421392076D5BD00FA9BE6 /* NetworkServiceConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkServiceConfiguration.swift; sourceTree = "<group>"; };
EFA4C66320864F9C008C4DD8 /* UniversalMappable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniversalMappable.swift; sourceTree = "<group>"; };
@ -1168,7 +1175,6 @@
67274783206CD7E500725163 /* DateFormatingService */,
672947E3206EA63200AC6B6B /* Drawing */,
671462281EB3396E00EAB194 /* LoadingIndicator.swift */,
671462291EB3396E00EAB194 /* ModuleConfigurator.swift */,
67C7B1772068BADA00C9EDA3 /* NumberFormattingService */,
A676AE541F981121001F9214 /* ObservableMappable.swift */,
6714622B1EB3396E00EAB194 /* ResettableType.swift */,
@ -1327,6 +1333,7 @@
isa = PBXGroup;
children = (
6792623A206EB0D800308E62 /* SeparatorCell */,
67ED2BE420B44F4300508B3E /* InitializableView+DefaultImplementation.swift */,
6727476D206CCDDB00725163 /* ViewBackground+Configuration.swift */,
6727477E206CD3BD00725163 /* ViewText+Extensions.swift */,
);
@ -1480,7 +1487,8 @@
67745266206248F00024EEEF /* PaginationDataLoading */ = {
isa = PBXGroup;
children = (
6774526F20624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift */,
6774526F20624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift */,
820CAD8320B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift */,
6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */,
67745267206249360024EEEF /* UITableView+PaginationWrappable.swift */,
);
@ -1560,6 +1568,7 @@
children = (
67EB7FFC206176C900BDD9FB /* AnyPaginationWrappable.swift */,
67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */,
825F8F2720B3384C00594857 /* PaginationWrapperUIDelegate.swift */,
);
path = PaginationDataLoading;
sourceTree = "<group>";
@ -1578,6 +1587,7 @@
children = (
67926234206EB08400308E62 /* SeparatorCell */,
678D269D20692BFF00B05B93 /* TextField */,
67ED2BDD20B44DEB00508B3E /* InitializableView.swift */,
);
path = Views;
sourceTree = "<group>";
@ -1772,6 +1782,7 @@
A6F32C0D1F6EBE7700AC08EE /* Extensions */ = {
isa = PBXGroup;
children = (
D93221ED20A44896003799D5 /* Double+RoundingTests.swift */,
A6F32C0E1F6EBE8E00AC08EE /* StringExtensionTests.swift */,
);
path = Extensions;
@ -2609,6 +2620,7 @@
67EB8001206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */,
67FD4382206BD24B005B0C64 /* EqutableOptionalArray.swift in Sources */,
6774529A20625E5B0024EEEF /* PaginationDataLoadingState.swift in Sources */,
825F8F2820B3384C00594857 /* PaginationWrapperUIDelegate.swift in Sources */,
678D26A020692BFF00B05B93 /* TextFieldViewEvents.swift in Sources */,
6727478F206CD88600725163 /* DateFormattingService.swift in Sources */,
678D26A420692BFF00B05B93 /* TextFieldViewModelEvents.swift in Sources */,
@ -2617,6 +2629,7 @@
671463541EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */,
673CF4112063ABD100C329F6 /* GeneralDataLoadingState+Extensions.swift in Sources */,
673CF42C2063DE5900C329F6 /* TextPlaceholderView.swift in Sources */,
67ED2BDE20B44DEB00508B3E /* InitializableView.swift in Sources */,
671463601EB3396E00EAB194 /* SupportProtocol.swift in Sources */,
671462841EB3396E00EAB194 /* CGContext+Initializers.swift in Sources */,
EFBE57DB1EC361620040E00A /* UIView+Layout.swift in Sources */,
@ -2628,7 +2641,6 @@
671463101EB3396E00EAB194 /* UIViewController+DefaultXibName.swift in Sources */,
67386A8C206CF3F6004EDA6C /* DateFormattingService+DefaultImplementation.swift in Sources */,
674AF55C1EC45B1600038A8F /* UIActivityIndicatorView+LoadingIndicator.swift in Sources */,
671463401EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */,
67A1FF8F1EBCA09B00D6C89F /* UIImage+Spinner.swift in Sources */,
673564F62068C68D00F0CBED /* NumberFormat.swift in Sources */,
EFA4C66420864F9C008C4DD8 /* UniversalMappable.swift in Sources */,
@ -2701,6 +2713,7 @@
671463081EB3396E00EAB194 /* UIView+Rotation.swift in Sources */,
6714626C1EB3396E00EAB194 /* XibView.swift in Sources */,
67274778206CD0B500725163 /* UILabel+ViewTextConfiguration.swift in Sources */,
67ED2BE520B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */,
6774529220625D170024EEEF /* GeneralDataLoadingModel.swift in Sources */,
6714637C1EB3396E00EAB194 /* ImageDrawingOperation.swift in Sources */,
671463341EB3396E00EAB194 /* DrawingOperation.swift in Sources */,
@ -2710,7 +2723,7 @@
671463981EB3396E00EAB194 /* AnyLoadingIndicator.swift in Sources */,
671463A71EB340C000EAB194 /* UIViewController+ConfigurableController.swift in Sources */,
671463141EB3396E00EAB194 /* UIViewController+TopVisibleViewController.swift in Sources */,
6774527020624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */,
6774527020624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift in Sources */,
6727478A206CD83600725163 /* DateFormat.swift in Sources */,
67745280206256A20024EEEF /* RxDataLoadingModel.swift in Sources */,
A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */,
@ -2736,6 +2749,7 @@
6714628C1EB3396E00EAB194 /* CGImage+Alpha.swift in Sources */,
671462741EB3396E00EAB194 /* LeadKitError.swift in Sources */,
677452A420625FA90024EEEF /* RxDataSource.swift in Sources */,
820CAD8420B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */,
671AD262206A35EC00EAF887 /* UIApplication+Cellular.swift in Sources */,
6713C23C20AF0D5900875921 /* NetworkOperationModel.swift in Sources */,
671462D81EB3396E00EAB194 /* TimeInterval+DateComponents.swift in Sources */,
@ -2763,17 +2777,14 @@
buildActionMask = 2147483647;
files = (
A6C9A5051F8BC78F009311CC /* SeparatorConfiguration.swift in Sources */,
D93221EE20A44896003799D5 /* Double+RoundingTests.swift in Sources */,
671463CA1EB34B1E00EAB194 /* TestView.swift in Sources */,
671463B81EB34B1E00EAB194 /* StubCursor.swift in Sources */,
A658E54E1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift in Sources */,
A658E5511F8CD9350093527A /* Array+SeparatorRowBoxExtensions.swift in Sources */,
671463BB1EB34B1E00EAB194 /* CursorTests.swift in Sources */,
A6F32C101F6EBE9600AC08EE /* StringExtensionTests.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 /* SeparatorRowBox.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2806,7 +2817,6 @@
6714626A1EB3396E00EAB194 /* NetworkService.swift in Sources */,
671AD26E206A3E8500EAF887 /* Array+TotalCountCursorListingResult.swift in Sources */,
673CF4132063ABD100C329F6 /* GeneralDataLoadingState+Extensions.swift in Sources */,
671463421EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */,
6713C24320AF189100875921 /* RxNetworkOperationModel.swift in Sources */,
671462921EB3396E00EAB194 /* CGImage+Crop.swift in Sources */,
671463861EB3396E00EAB194 /* ResizeDrawingOperation.swift in Sources */,
@ -2822,6 +2832,7 @@
6714638A1EB3396E00EAB194 /* RoundDrawingOperation.swift in Sources */,
67153E3C207DFADA0049D8C0 /* RotateDrawingOperation.swift in Sources */,
6774529C20625E5B0024EEEF /* PaginationDataLoadingState.swift in Sources */,
67ED2BE020B44DEB00508B3E /* InitializableView.swift in Sources */,
671463821EB3396E00EAB194 /* PaddingDrawingOperation.swift in Sources */,
6714632A1EB3396E00EAB194 /* BaseViewModel.swift in Sources */,
671462AE1EB3396E00EAB194 /* Observable+DeferredJust.swift in Sources */,
@ -2880,6 +2891,7 @@
67FDC2611FA310EA00C76A77 /* RequestError.swift in Sources */,
671AD25E206A343300EAF887 /* VoidBlock.swift in Sources */,
671462521EB3396E00EAB194 /* StaticCursor.swift in Sources */,
67ED2BE720B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */,
6714629E1EB3396E00EAB194 /* CursorType+Slice.swift in Sources */,
6714636A1EB3396E00EAB194 /* ConfigurableView.swift in Sources */,
);
@ -2891,16 +2903,17 @@
files = (
6714634B1EB3396E00EAB194 /* ResettableType.swift in Sources */,
671462E71EB3396E00EAB194 /* UIColor+Hex.swift in Sources */,
67ED2BE120B44DEB00508B3E /* InitializableView.swift in Sources */,
67274775206CCF1200725163 /* ViewText.swift in Sources */,
6727476B206CCCA500725163 /* ViewBackground.swift in Sources */,
671462831EB3396E00EAB194 /* AlamofireRequest+Extensions.swift in Sources */,
67ED2BE820B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */,
677452B820627FE00024EEEF /* PaginationWrappable.swift in Sources */,
673CF40E2063AB7C00C329F6 /* GeneralDataLoadingViewModel.swift in Sources */,
67274770206CCDDB00725163 /* ViewBackground+Configuration.swift in Sources */,
678D26A320692BFF00B05B93 /* TextFieldViewEvents.swift in Sources */,
67153E43207DFBA80049D8C0 /* FloatingPoint+DegreesRadiansConvertion.swift in Sources */,
67745283206256A20024EEEF /* RxDataLoadingModel.swift in Sources */,
67EB8003206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */,
671463571EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */,
671463631EB3396E00EAB194 /* SupportProtocol.swift in Sources */,
671462871EB3396E00EAB194 /* CGContext+Initializers.swift in Sources */,
@ -2909,7 +2922,6 @@
6714626B1EB3396E00EAB194 /* NetworkService.swift in Sources */,
673CF43A2063E7CE00C329F6 /* GeneralDataLoadingController+DefaultImplementation.swift in Sources */,
671463131EB3396E00EAB194 /* UIViewController+DefaultXibName.swift in Sources */,
671463431EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */,
671462931EB3396E00EAB194 /* CGImage+Crop.swift in Sources */,
6727477A206CD0B500725163 /* UILabel+ViewTextConfiguration.swift in Sources */,
67EB7FE720615DE000BDD9FB /* DataSource.swift in Sources */,
@ -3040,6 +3052,7 @@
671463BA1EB34B1E00EAB194 /* StubCursor.swift in Sources */,
671463BD1EB34B1E00EAB194 /* CursorTests.swift in Sources */,
A6F32C121F6EBE9800AC08EE /* StringExtensionTests.swift in Sources */,
D93221F020A44896003799D5 /* Double+RoundingTests.swift in Sources */,
671463C01EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */,
671463C61EB34B1E00EAB194 /* Post.swift in Sources */,
);
@ -3075,7 +3088,6 @@
671462F11EB3396E00EAB194 /* UIImage+SupportExtensions.swift in Sources */,
671462691EB3396E00EAB194 /* NetworkService.swift in Sources */,
671463111EB3396E00EAB194 /* UIViewController+DefaultXibName.swift in Sources */,
671463411EB3396E00EAB194 /* ModuleConfigurator.swift in Sources */,
EFA4C67020865126008C4DD8 /* UniversalMappable+SwiftStandard.swift in Sources */,
67153E41207DFBA80049D8C0 /* FloatingPoint+DegreesRadiansConvertion.swift in Sources */,
671462911EB3396E00EAB194 /* CGImage+Crop.swift in Sources */,
@ -3093,6 +3105,7 @@
67EB7FEC2061667900BDD9FB /* DefaultTotalCountCursorListingResult.swift in Sources */,
671462991EB3396E00EAB194 /* CGSize+Resize.swift in Sources */,
67274780206CD3BD00725163 /* ViewText+Extensions.swift in Sources */,
67ED2BE620B44F4300508B3E /* InitializableView+DefaultImplementation.swift in Sources */,
671463311EB3396E00EAB194 /* CursorType.swift in Sources */,
6714624D1EB3396E00EAB194 /* MapCursor.swift in Sources */,
67EB7FD520615D1700BDD9FB /* ResettableCursorType.swift in Sources */,
@ -3109,7 +3122,6 @@
6774526D206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */,
6714627D1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */,
673CF4352063E29B00C329F6 /* TextWithButtonPlaceholder.swift in Sources */,
67EB8002206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */,
6727476F206CCDDB00725163 /* ViewBackground+Configuration.swift in Sources */,
673CF4232063D90600C329F6 /* DisposeBagHolder.swift in Sources */,
677452AA206263360024EEEF /* CursorType+RxDataSourceDefaultImplementation.swift in Sources */,
@ -3122,6 +3134,7 @@
6713C24220AF189100875921 /* RxNetworkOperationModel.swift in Sources */,
671462A11EB3396E00EAB194 /* Double+Rounding.swift in Sources */,
671463091EB3396E00EAB194 /* UIView+Rotation.swift in Sources */,
67ED2BDF20B44DEB00508B3E /* InitializableView.swift in Sources */,
6714626D1EB3396E00EAB194 /* XibView.swift in Sources */,
6714637D1EB3396E00EAB194 /* ImageDrawingOperation.swift in Sources */,
671463351EB3396E00EAB194 /* DrawingOperation.swift in Sources */,
@ -3198,6 +3211,7 @@
671463BF1EB34B1E00EAB194 /* LoadFromNibTests.swift in Sources */,
671463C51EB34B1E00EAB194 /* Post.swift in Sources */,
671463CB1EB34B1E00EAB194 /* TestView.swift in Sources */,
D93221EF20A44896003799D5 /* Double+RoundingTests.swift in Sources */,
A6F32C111F6EBE9700AC08EE /* StringExtensionTests.swift in Sources */,
671463BC1EB34B1E00EAB194 /* CursorTests.swift in Sources */,
671463B91EB34B1E00EAB194 /* StubCursor.swift in Sources */,

View File

@ -36,6 +36,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
private var wrappedView: AnyPaginationWrappable
private let paginationViewModel: DataLoadingModel
private weak var delegate: Delegate?
private weak var uiDelegate: PaginationWrapperUIDelegate?
/// Sets the offset between the real end of the scroll view content and the scroll position,
/// so the handler can be triggered before reaching end. Defaults to 0.0;
@ -70,10 +71,15 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
/// - Parameters:
/// - wrappedView: UIScrollView instance to work with.
/// - cursor: Cursor object that acts as data source.
/// - delegate: Delegate object for data loading events handling and UI customization.
public init(wrappedView: AnyPaginationWrappable, cursor: Cursor, delegate: Delegate) {
/// - delegate: Delegate object for data loading events handling.
/// - uiDelegate: Delegate object for UI customization.
public init(wrappedView: AnyPaginationWrappable,
cursor: Cursor,
delegate: Delegate,
uiDelegate: PaginationWrapperUIDelegate? = nil) {
self.wrappedView = wrappedView
self.delegate = delegate
self.uiDelegate = uiDelegate
self.paginationViewModel = PaginationDataLoadingModel(cursor: cursor)
@ -116,7 +122,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
removeCurrentPlaceholderView()
guard let loadingIndicator = delegate?.initialLoadingIndicator() else {
guard let loadingIndicator = uiDelegate?.initialLoadingIndicator() else {
return
}
@ -137,7 +143,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
private func onLoadingMoreState(afterState: LoadingState) {
if case .error = afterState { // user tap retry button in table footer
delegate?.footerRetryButtonWillDisappear()
uiDelegate?.footerRetryButtonWillDisappear()
wrappedView.footerView = nil
addInfiniteScroll(withHandler: false)
wrappedView.scrollView.beginInfiniteScroll(true)
@ -171,20 +177,19 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
wrappedView.scrollView.support.refreshControl?.endRefreshing()
}
let customErrorHandling = delegate?.customInitialLoadingErrorHandling(for: error) ?? false
delegate?.clearData()
guard !customErrorHandling, let errorView = delegate?.errorPlaceholder(for: error) else {
let customErrorHandling = uiDelegate?.customInitialLoadingErrorHandling(for: error) ?? false
guard !customErrorHandling, let errorView = uiDelegate?.errorPlaceholder(for: error) else {
return
}
replacePlaceholderViewIfNeeded(with: errorView)
delegate?.clearView()
} else if case .loadingMore = afterState {
removeInfiniteScroll()
guard let retryButton = delegate?.footerRetryButton(),
let retryButtonHeigth = delegate?.footerRetryButtonHeight() else {
guard let retryButton = uiDelegate?.footerRetryButton(),
let retryButtonHeigth = uiDelegate?.footerRetryButtonHeight() else {
return
}
@ -196,7 +201,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
.drive(retryEvent)
.disposed(by: disposeBag)
delegate?.footerRetryButtonWillAppear()
uiDelegate?.footerRetryButtonWillAppear()
wrappedView.footerView = retryButton
}
@ -207,9 +212,9 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
wrappedView.scrollView.support.refreshControl?.endRefreshing()
}
delegate?.clearView()
delegate?.clearData()
guard let emptyView = delegate?.emptyPlaceholder() else {
guard let emptyView = uiDelegate?.emptyPlaceholder() else {
return
}
@ -264,7 +269,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
wrappedView.scrollView.addInfiniteScroll { _ in }
}
wrappedView.scrollView.infiniteScrollIndicatorView = delegate?.loadingMoreIndicator().view
wrappedView.scrollView.infiniteScrollIndicatorView = uiDelegate?.loadingMoreIndicator().view
}
private func removeInfiniteScroll() {

View File

@ -41,7 +41,7 @@ public extension GeneralDataLoadingController where Self: UIViewController {
func initialLoadDataLoadingView() {
addViews()
setAppearance()
configureAppearance()
setupStateViews()
configureBarButtons()
localize()

View File

@ -20,62 +20,10 @@
// THE SOFTWARE.
//
import UIKit
public extension PaginationWrapperDelegate {
func emptyPlaceholder() -> UIView {
return TextPlaceholderView(title: .empty)
}
func customInitialLoadingErrorHandling(for error: Error) -> Bool {
return false
}
func errorPlaceholder(for error: Error) -> UIView {
return TextPlaceholderView(title: .error)
}
func initialLoadingIndicator() -> AnyLoadingIndicator {
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
indicator.color = .gray
return AnyLoadingIndicator(indicator)
}
func loadingMoreIndicator() -> AnyLoadingIndicator {
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
return AnyLoadingIndicator(indicator)
}
func footerRetryButton() -> UIButton {
let retryButton = UIButton(type: .custom)
retryButton.backgroundColor = .lightGray
retryButton.setTitle("Retry load more", for: .normal)
return retryButton
}
func footerRetryButtonHeight() -> CGFloat {
return 44
}
func footerRetryButtonWillAppear() {
// by default - nothing will happen
}
func footerRetryButtonWillDisappear() {
// by default - nothing will happen
}
}
public extension PaginationWrapperDelegate
where DataSourceType: ResettableRxDataSourceCursor,
DataSourceType.ResultType == [DataSourceType.Element] {
DataSourceType.ResultType == [DataSourceType.Element] {
/// Convenient typealias.
typealias PaginationWrapperType = PaginationWrapper<DataSourceType, Self>
}

View File

@ -0,0 +1,71 @@
//
// Copyright (c) 2018 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 extension PaginationWrapperUIDelegate {
func emptyPlaceholder() -> UIView {
return TextPlaceholderView(title: .empty)
}
func customInitialLoadingErrorHandling(for error: Error) -> Bool {
return false
}
func errorPlaceholder(for error: Error) -> UIView {
return TextPlaceholderView(title: .error)
}
func initialLoadingIndicator() -> AnyLoadingIndicator {
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
indicator.color = .gray
return AnyLoadingIndicator(indicator)
}
func loadingMoreIndicator() -> AnyLoadingIndicator {
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
return AnyLoadingIndicator(indicator)
}
func footerRetryButton() -> UIButton {
let retryButton = UIButton(type: .custom)
retryButton.backgroundColor = .lightGray
retryButton.setTitle("Retry load more", for: .normal)
return retryButton
}
func footerRetryButtonHeight() -> CGFloat {
return 44
}
func footerRetryButtonWillAppear() {
// by default - nothing will happen
}
func footerRetryButtonWillDisappear() {
// by default - nothing will happen
}
}

View File

@ -23,10 +23,8 @@
import Foundation
public extension Double {
/**
Type of rounding double value
- Normal: From 167.567 you will get 167.6
- Down: From 167.567 you will get 167.5
*/
@ -37,19 +35,17 @@ public extension Double {
/**
Rounding of double value
- parameter persicion: important number of digits after comma
- parameter precision: significant digits after decimal point
- parameter roundType: rounding type
- returns: rounded value
*/
func roundValue(withPersicion persicion: UInt,
func roundValue(withPrecision precision: UInt,
roundType: RoundingType = .normal) -> Double {
let divider = pow(10.0, Double(persicion))
let divider = pow(10.0, Double(precision))
switch roundType {
case .normal:
return (self * divider).rounded(.up) / divider
return (self * divider).rounded(.toNearestOrEven) / divider
case .down:
return (self * divider).rounded(.down) / divider
}

View File

@ -24,29 +24,13 @@ import UIKit
public extension ConfigurableController where Self: UIViewController {
func bindViews() {
// nothing
}
func addViews() {
// nothing
}
func setAppearance() {
// nothing
}
func configureBarButtons() {
// nothing
}
func localize() {
// nothing
}
func initialLoadView() {
addViews()
setAppearance()
configureAppearance()
configureBarButtons()
localize()
bindViews()

View File

@ -1,8 +1,8 @@
//
// Copyright (c) 2017 Touch Instinct
// Copyright (c) 2018 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
// 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
@ -11,7 +11,7 @@
// 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
// 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
@ -20,9 +20,29 @@
// THE SOFTWARE.
//
public protocol ModuleConfigurator {
public extension InitializableView {
associatedtype ViewControllerT
func initializeView() {
addViews()
bindViews()
configureAppearance()
localize()
}
func addViews() {
//
}
func bindViews() {
//
}
func configureAppearance() {
//
}
func localize() {
//
}
func configure(input: ViewControllerT)
}

View File

@ -22,22 +22,14 @@
import Foundation
public protocol ConfigurableController {
public protocol ConfigurableController: InitializableView {
associatedtype ViewModelT
var viewModel: ViewModelT! { get }
func bindViews()
func addViews()
func setAppearance()
var viewModel: ViewModelT { get }
func configureBarButtons()
func localize()
func initialLoadView()
}

View File

@ -0,0 +1,41 @@
//
// Copyright (c) 2018 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.
//
/// Protocol with methods that should be called in constructor methods of view.
public protocol InitializableView {
/// Main method that should call other in particular order.
func initializeView()
/// Method for adding views to current view.
func addViews()
/// Method for binding to data or user actions.
func bindViews()
/// Appearance configuration method.
func configureAppearance()
/// Localization method.
func localize()
}

View File

@ -20,8 +20,7 @@
// THE SOFTWARE.
//
/// PaginationWrapper delegate used for pagination results handling and
/// customization of bound states (loading, empty, error, etc.).
/// PaginationWrapper delegate used for pagination results handling
public protocol PaginationWrapperDelegate: class {
associatedtype DataSourceType: DataSource
@ -42,56 +41,6 @@ public protocol PaginationWrapperDelegate: class {
func paginationWrapper(didReload allItems: DataSourceType.ResultType,
using dataSource: DataSourceType)
/// Returns placeholder view for empty state.
///
/// - Returns: Configured instace of UIView.
func emptyPlaceholder() -> UIView
/// Called when initial loading error is occured.
/// It should return true if error is handled and false if it doesn't.
///
/// - Parameters:
/// - error: Error that occured due data loading.
/// - Returns: Bool value. If true - then error placeholder wouldn't be shown.
func customInitialLoadingErrorHandling(for error: Error) -> Bool
/// Returns placeholder view for error state.
///
/// - Parameters:
/// - error: Error that occured due data loading.
/// - Returns: Configured instace of UIView.
func errorPlaceholder(for error: Error) -> UIView
/// Returns loading idicator for initial loading state.
/// This indicator will appear at center of the placeholders container.
///
/// - Returns: Configured instace of AnyLoadingIndicator.
func initialLoadingIndicator() -> AnyLoadingIndicator
/// Returns loading idicator for initial loading state.
///
/// - Returns: Configured instace of AnyLoadingIndicator.
func loadingMoreIndicator() -> AnyLoadingIndicator
/// Returns instance of UIButton for "retry load more" action.
///
/// - Returns: Configured instace of AnyLoadingIndicator.
func footerRetryButton() -> UIButton
/// Returns height for "retry load more" button.
///
/// - Returns: Height of "retry load more" button.
func footerRetryButtonHeight() -> CGFloat
/// Method is called before "retry load more" will be shown.
/// Typically, it's used when you need to show custom footer view.
func footerRetryButtonWillAppear()
/// Method is called before "retry load more" will be hidden.
/// Typically, it's used when you need to hide custom footer view.
func footerRetryButtonWillDisappear()
/// Clears view when placeholder is shown.
func clearView()
/// Handles empty data state.
func clearData()
}

View File

@ -0,0 +1,75 @@
//
// Copyright (c) 2018 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.
//
/// PaginationWrapper UI delegate used for customization
/// of bound states (loading, empty, error, etc.).
public protocol PaginationWrapperUIDelegate: class {
/// Returns placeholder view for empty state.
///
/// - Returns: Configured instace of UIView.
func emptyPlaceholder() -> UIView?
/// Called when initial loading error is occured.
/// It should return true if error is handled and false if it doesn't.
///
/// - Parameters:
/// - error: Error that occured due data loading.
/// - Returns: Bool value. If true - then error placeholder wouldn't be shown.
func customInitialLoadingErrorHandling(for error: Error) -> Bool
/// Returns placeholder view for error state.
///
/// - Parameters:
/// - error: Error that occured due data loading.
/// - Returns: Configured instace of UIView.
func errorPlaceholder(for error: Error) -> UIView?
/// Returns loading idicator for initial loading state.
/// This indicator will appear at center of the placeholders container.
///
/// - Returns: Configured instace of AnyLoadingIndicator.
func initialLoadingIndicator() -> AnyLoadingIndicator?
/// Returns loading idicator for initial loading state.
///
/// - Returns: Configured instace of AnyLoadingIndicator.
func loadingMoreIndicator() -> AnyLoadingIndicator?
/// Returns instance of UIButton for "retry load more" action.
///
/// - Returns: Configured instace of AnyLoadingIndicator.
func footerRetryButton() -> UIButton?
/// Returns height for "retry load more" button.
///
/// - Returns: Height of "retry load more" button.
func footerRetryButtonHeight() -> CGFloat
/// Method is called before "retry load more" will be shown.
/// Typically, it's used when you need to show custom footer view.
func footerRetryButtonWillAppear()
/// Method is called before "retry load more" will be hidden.
/// Typically, it's used when you need to hide custom footer view.
func footerRetryButtonWillDisappear()
}

View File

@ -0,0 +1,54 @@
//
// 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 XCTest
class Double_RoundingTests: XCTestCase {
func testPositiveNumbers() {
let pi = 3.1415926
XCTAssertTrue(pi.roundValue(withPrecision: 0) == 3.0)
XCTAssertTrue(pi.roundValue(withPrecision: 1) == 3.1)
XCTAssertTrue(pi.roundValue(withPrecision: 2) == 3.14)
XCTAssertTrue(pi.roundValue(withPrecision: 3) == 3.142)
let some = 1.778297
XCTAssertTrue(some.roundValue(withPrecision: 1) == 1.8)
XCTAssertTrue(some.roundValue(withPrecision: 1, roundType: .down) == 1.7)
XCTAssertTrue(some.roundValue(withPrecision: 2, roundType: .down) == 1.77)
}
func testNegativeNumbers() {
let e = 2.7182
XCTAssertTrue(-e.roundValue(withPrecision: 0) == -3.0)
XCTAssertTrue(-e.roundValue(withPrecision: 1) == -2.7)
XCTAssertTrue(-e.roundValue(withPrecision: 2) == -2.72)
XCTAssertTrue(-e.roundValue(withPrecision: 3) == -2.718)
let some = -1.778297
XCTAssertTrue(some.roundValue(withPrecision: 1) == -1.8)
XCTAssertTrue(some.roundValue(withPrecision: 1, roundType: .down) == -1.8)
XCTAssertTrue(some.roundValue(withPrecision: 2, roundType: .down) == -1.78)
}
}