base implementation of text cell view model. remove old implementation of same stuff

This commit is contained in:
Ivan Smolin 2018-03-26 23:41:05 +03:00
parent 17561204c3
commit 4988dd65d9
16 changed files with 360 additions and 514 deletions

View File

@ -7,10 +7,17 @@
objects = {
/* Begin PBXBuildFile section */
0A08E37F1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */; };
248389A288C0A6D7914F0546 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ED4A1B793EAA73C9E95969F /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */; };
67779CBC206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */; };
67779CBD206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */; };
678D26AA206935B900B05B93 /* BiometricsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678D26A9206935B900B05B93 /* BiometricsService.swift */; };
67B4E6EB206941CE00E233EA /* BiometricsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 678D26A9206935B900B05B93 /* BiometricsService.swift */; };
67B4E6F3206945D200E233EA /* BaseTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */; };
67B4E6F6206945DD00E233EA /* OnlineValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */; };
67B4E6F7206945DD00E233EA /* OnlineValidationResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */; };
67B4E6F9206945F900E233EA /* OnlineValidationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F8206945F900E233EA /* OnlineValidationState.swift */; };
67B4E6FA206945F900E233EA /* OnlineValidationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F8206945F900E233EA /* OnlineValidationState.swift */; };
67B4E6FB20694A4200E233EA /* BaseTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */; };
A6CFB8D91F5024A500A42CC2 /* Error+NetworkingExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */; };
B326804BA6CC8B8BB136A46A /* Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFD5627139CAB27705F75C07 /* Pods_LeadKitAdditions_LeadKitAdditions_iOS_Extensions.framework */; };
CAE698E81E968820000394B0 /* LeadKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE698E61E968820000394B0 /* LeadKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -44,22 +51,10 @@
ED0C34201F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */; };
ED0C34211F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */; };
ED0C34221F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */; };
ED0C34231F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EB1F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift */; };
ED0C34241F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EB1F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift */; };
ED0C34251F2906EC00FAE9FD /* CellFieldMaskProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EC1F2906EC00FAE9FD /* CellFieldMaskProtocol.swift */; };
ED0C34261F2906EC00FAE9FD /* CellFieldMaskProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EC1F2906EC00FAE9FD /* CellFieldMaskProtocol.swift */; };
ED0C34271F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33ED1F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift */; };
ED0C34281F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33ED1F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift */; };
ED0C34291F2906EC00FAE9FD /* CellFieldValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EE1F2906EC00FAE9FD /* CellFieldValidationProtocol.swift */; };
ED0C342A1F2906EC00FAE9FD /* CellFieldValidationProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EE1F2906EC00FAE9FD /* CellFieldValidationProtocol.swift */; };
ED0C342B1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EF1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift */; };
ED0C342C1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33EF1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift */; };
ED0C342D1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F11F2906EC00FAE9FD /* BasePassCodeService.swift */; };
ED0C342E1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F11F2906EC00FAE9FD /* BasePassCodeService.swift */; };
ED0C342F1F2906EC00FAE9FD /* BaseUserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F21F2906EC00FAE9FD /* BaseUserService.swift */; };
ED0C34301F2906EC00FAE9FD /* BaseUserService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F21F2906EC00FAE9FD /* BaseUserService.swift */; };
ED0C34311F2906EC00FAE9FD /* CellFieldsJumpingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F31F2906EC00FAE9FD /* CellFieldsJumpingService.swift */; };
ED0C34321F2906EC00FAE9FD /* CellFieldsJumpingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F31F2906EC00FAE9FD /* CellFieldsJumpingService.swift */; };
ED0C34331F2906EC00FAE9FD /* MaskFieldTextProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F41F2906EC00FAE9FD /* MaskFieldTextProxy.swift */; };
ED0C34341F2906EC00FAE9FD /* MaskFieldTextProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F41F2906EC00FAE9FD /* MaskFieldTextProxy.swift */; };
ED0C34351F2906EC00FAE9FD /* ApiNetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33F61F2906EC00FAE9FD /* ApiNetworkService.swift */; };
@ -74,20 +69,18 @@
ED0C34421F2906EC00FAE9FD /* ValidationItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */; };
ED0C34431F2906EC00FAE9FD /* ValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */; };
ED0C34441F2906EC00FAE9FD /* ValidationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */; };
ED0C34451F2906EC00FAE9FD /* CellTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C34011F2906EC00FAE9FD /* CellTextField.swift */; };
ED0C34461F2906EC00FAE9FD /* CellTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C34011F2906EC00FAE9FD /* CellTextField.swift */; };
ED0C34471F2906EC00FAE9FD /* CellTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C34021F2906EC00FAE9FD /* CellTextFieldViewModel.swift */; };
ED0C34481F2906EC00FAE9FD /* CellTextFieldViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED0C34021F2906EC00FAE9FD /* CellTextFieldViewModel.swift */; };
ED69E7E81F2AC7CC00C74895 /* CellTextFieldToolBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */; };
EFBD55921EBB9A980062AA63 /* LeadKitAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = CAE698E61E968820000394B0 /* LeadKitAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
01605ECA03749D49C27FA3DD /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.release.xcconfig"; sourceTree = "<group>"; };
0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellTextFieldToolBar.swift; sourceTree = "<group>"; };
0ED4A1B793EAA73C9E95969F /* Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitAdditions_LeadKitAdditions_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
49738551AC648B0AFA74E57F /* Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS/Pods-LeadKitAdditions-LeadKitAdditions iOS.debug.xcconfig"; sourceTree = "<group>"; };
67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BaseTextFieldViewEvents+Extensions.swift"; sourceTree = "<group>"; };
678D26A9206935B900B05B93 /* BiometricsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BiometricsService.swift; sourceTree = "<group>"; };
67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTextFieldViewModel.swift; sourceTree = "<group>"; };
67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnlineValidationResult.swift; sourceTree = "<group>"; };
67B4E6F8206945F900E233EA /* OnlineValidationState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnlineValidationState.swift; sourceTree = "<group>"; };
7B7F57C5E5275C4D8DC71992 /* Pods_LeadKitAdditions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKitAdditions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9D549FA5A7579702358E07DF /* Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions/Pods-LeadKitAdditions-LeadKitAdditions iOS Extensions.debug.xcconfig"; sourceTree = "<group>"; };
A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Error+NetworkingExtensions.swift"; sourceTree = "<group>"; };
@ -110,14 +103,8 @@
ED0C33E71F2906EC00FAE9FD /* Observable+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+Extensions.swift"; sourceTree = "<group>"; };
ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem+Extensions.swift"; sourceTree = "<group>"; };
ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDefaults+UserService.swift"; sourceTree = "<group>"; };
ED0C33EB1F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellFieldJumpingProtocol.swift; sourceTree = "<group>"; };
ED0C33EC1F2906EC00FAE9FD /* CellFieldMaskProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellFieldMaskProtocol.swift; sourceTree = "<group>"; };
ED0C33ED1F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellFieldsToolBarProtocol.swift; sourceTree = "<group>"; };
ED0C33EE1F2906EC00FAE9FD /* CellFieldValidationProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellFieldValidationProtocol.swift; sourceTree = "<group>"; };
ED0C33EF1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormCellViewModelProtocol.swift; sourceTree = "<group>"; };
ED0C33F11F2906EC00FAE9FD /* BasePassCodeService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BasePassCodeService.swift; sourceTree = "<group>"; };
ED0C33F21F2906EC00FAE9FD /* BaseUserService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseUserService.swift; sourceTree = "<group>"; };
ED0C33F31F2906EC00FAE9FD /* CellFieldsJumpingService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellFieldsJumpingService.swift; sourceTree = "<group>"; };
ED0C33F41F2906EC00FAE9FD /* MaskFieldTextProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MaskFieldTextProxy.swift; sourceTree = "<group>"; };
ED0C33F61F2906EC00FAE9FD /* ApiNetworkService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApiNetworkService.swift; sourceTree = "<group>"; };
ED0C33F71F2906EC00FAE9FD /* DefaultNetworkService+ActivityIndicator+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DefaultNetworkService+ActivityIndicator+Extension.swift"; sourceTree = "<group>"; };
@ -126,8 +113,6 @@
ED0C33FC1F2906EC00FAE9FD /* ValidationError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationError.swift; sourceTree = "<group>"; };
ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationItem.swift; sourceTree = "<group>"; };
ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ValidationService.swift; sourceTree = "<group>"; };
ED0C34011F2906EC00FAE9FD /* CellTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellTextField.swift; sourceTree = "<group>"; };
ED0C34021F2906EC00FAE9FD /* CellTextFieldViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellTextFieldViewModel.swift; sourceTree = "<group>"; };
EFBD55701EBB87100062AA63 /* LeadKitAdditions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LeadKitAdditions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EFBD55781EBB893F0062AA63 /* Info-iOS-Extensions.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS-Extensions.plist"; sourceTree = "<group>"; };
EFBD55791EBB893F0062AA63 /* Info-iOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
@ -153,6 +138,22 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
67B4E6F0206945D200E233EA /* BaseTextFieldViewModel */ = {
isa = PBXGroup;
children = (
67B4E6F1206945D200E233EA /* BaseTextFieldViewModel.swift */,
);
path = BaseTextFieldViewModel;
sourceTree = "<group>";
};
67B4E6F4206945DC00E233EA /* ValidationService */ = {
isa = PBXGroup;
children = (
67B4E6F5206945DC00E233EA /* OnlineValidationResult.swift */,
);
path = ValidationService;
sourceTree = "<group>";
};
A3117951840B8B7D2E7A8A80 /* Frameworks */ = {
isa = PBXGroup;
children = (
@ -202,6 +203,7 @@
ED0C33D21F2906EC00FAE9FD /* Classes */ = {
isa = PBXGroup;
children = (
67B4E6F0206945D200E233EA /* BaseTextFieldViewModel */,
ED0C33D31F2906EC00FAE9FD /* ApiResponse.swift */,
ED0C33D41F2906EC00FAE9FD /* BaseDateFormatter.swift */,
ED0C33D51F2906EC00FAE9FD /* LoadingBarButton.swift */,
@ -271,6 +273,7 @@
ED0C33E81F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift */,
ED0C33E91F2906EC00FAE9FD /* UserDefaults+UserService.swift */,
A6CFB8D81F5024A500A42CC2 /* Error+NetworkingExtensions.swift */,
67779CBB206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift */,
);
path = Extensions;
sourceTree = "<group>";
@ -278,11 +281,7 @@
ED0C33EA1F2906EC00FAE9FD /* Protocols */ = {
isa = PBXGroup;
children = (
ED0C33EB1F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift */,
ED0C33EC1F2906EC00FAE9FD /* CellFieldMaskProtocol.swift */,
ED0C33EE1F2906EC00FAE9FD /* CellFieldValidationProtocol.swift */,
ED0C33ED1F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift */,
ED0C33EF1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift */,
67B4E6F4206945DC00E233EA /* ValidationService */,
);
path = Protocols;
sourceTree = "<group>";
@ -294,7 +293,6 @@
ED0C33FB1F2906EC00FAE9FD /* ValidationService */,
ED0C33F11F2906EC00FAE9FD /* BasePassCodeService.swift */,
ED0C33F21F2906EC00FAE9FD /* BaseUserService.swift */,
ED0C33F31F2906EC00FAE9FD /* CellFieldsJumpingService.swift */,
ED0C33F41F2906EC00FAE9FD /* MaskFieldTextProxy.swift */,
678D26A9206935B900B05B93 /* BiometricsService.swift */,
);
@ -315,6 +313,7 @@
ED0C33FB1F2906EC00FAE9FD /* ValidationService */ = {
isa = PBXGroup;
children = (
67B4E6F8206945F900E233EA /* OnlineValidationState.swift */,
ED0C33FC1F2906EC00FAE9FD /* ValidationError.swift */,
ED0C33FD1F2906EC00FAE9FD /* ValidationItem.swift */,
ED0C33FE1F2906EC00FAE9FD /* ValidationService.swift */,
@ -325,21 +324,10 @@
ED0C33FF1F2906EC00FAE9FD /* Views */ = {
isa = PBXGroup;
children = (
0A08E37E1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift */,
ED0C34001F2906EC00FAE9FD /* CellTextField */,
);
path = Views;
sourceTree = "<group>";
};
ED0C34001F2906EC00FAE9FD /* CellTextField */ = {
isa = PBXGroup;
children = (
ED0C34011F2906EC00FAE9FD /* CellTextField.swift */,
ED0C34021F2906EC00FAE9FD /* CellTextFieldViewModel.swift */,
);
path = CellTextField;
sourceTree = "<group>";
};
F8A65FEC7C0EB4B93746E50F /* Pods */ = {
isa = PBXGroup;
children = (
@ -573,39 +561,34 @@
buildActionMask = 2147483647;
files = (
ED0C34171F2906EC00FAE9FD /* ApiError.swift in Sources */,
67B4E6FB20694A4200E233EA /* BaseTextFieldViewModel.swift in Sources */,
ED0C343B1F2906EC00FAE9FD /* DefaultNetworkService.swift in Sources */,
ED0C34351F2906EC00FAE9FD /* ApiNetworkService.swift in Sources */,
ED0C340F1F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */,
ED0C343F1F2906EC00FAE9FD /* ValidationError.swift in Sources */,
ED0C342F1F2906EC00FAE9FD /* BaseUserService.swift in Sources */,
ED0C34231F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift in Sources */,
678D26AA206935B900B05B93 /* BiometricsService.swift in Sources */,
ED0C34411F2906EC00FAE9FD /* ValidationItem.swift in Sources */,
ED0C341F1F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */,
ED0C34091F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */,
ED0C342B1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift in Sources */,
ED0C341D1F2906EC00FAE9FD /* Observable+Extensions.swift in Sources */,
ED0C34471F2906EC00FAE9FD /* CellTextFieldViewModel.swift in Sources */,
ED0C34191F2906EC00FAE9FD /* ApiErrorProtocol.swift in Sources */,
ED0C34131F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */,
ED0C342D1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */,
67B4E6F9206945F900E233EA /* OnlineValidationState.swift in Sources */,
67779CBC206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */,
ED0C340D1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */,
ED0C34451F2906EC00FAE9FD /* CellTextField.swift in Sources */,
ED0C34271F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift in Sources */,
ED0C34291F2906EC00FAE9FD /* CellFieldValidationProtocol.swift in Sources */,
0A08E37F1F2A13BF00F9AB62 /* CellTextFieldToolBar.swift in Sources */,
ED0C34031F2906EC00FAE9FD /* ApiResponse.swift in Sources */,
A6CFB8D91F5024A500A42CC2 /* Error+NetworkingExtensions.swift in Sources */,
ED0C34071F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */,
ED0C34251F2906EC00FAE9FD /* CellFieldMaskProtocol.swift in Sources */,
ED0C34211F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */,
ED0C34391F2906EC00FAE9FD /* DefaultNetworkService+ActivityIndicator.swift in Sources */,
ED0C34311F2906EC00FAE9FD /* CellFieldsJumpingService.swift in Sources */,
ED0C34111F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */,
ED0C34051F2906EC00FAE9FD /* BaseDateFormatter.swift in Sources */,
ED0C34431F2906EC00FAE9FD /* ValidationService.swift in Sources */,
ED0C34331F2906EC00FAE9FD /* MaskFieldTextProxy.swift in Sources */,
ED0C340B1F2906EC00FAE9FD /* PassCodeError.swift in Sources */,
67B4E6F6206945DD00E233EA /* OnlineValidationResult.swift in Sources */,
ED0C34151F2906EC00FAE9FD /* BasePassCodeViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -616,32 +599,27 @@
files = (
ED0C34181F2906EC00FAE9FD /* ApiError.swift in Sources */,
ED0C343C1F2906EC00FAE9FD /* DefaultNetworkService.swift in Sources */,
67779CBD206986390098F024 /* BaseTextFieldViewEvents+Extensions.swift in Sources */,
ED0C34361F2906EC00FAE9FD /* ApiNetworkService.swift in Sources */,
ED0C34101F2906EC00FAE9FD /* PassCodeHolderProtocol.swift in Sources */,
ED0C34401F2906EC00FAE9FD /* ValidationError.swift in Sources */,
ED0C34301F2906EC00FAE9FD /* BaseUserService.swift in Sources */,
ED0C34241F2906EC00FAE9FD /* CellFieldJumpingProtocol.swift in Sources */,
ED0C34421F2906EC00FAE9FD /* ValidationItem.swift in Sources */,
ED0C34201F2906EC00FAE9FD /* UIBarButtonItem+Extensions.swift in Sources */,
ED0C340A1F2906EC00FAE9FD /* PassCodeConfiguration.swift in Sources */,
ED0C342C1F2906EC00FAE9FD /* FormCellViewModelProtocol.swift in Sources */,
67B4E6FA206945F900E233EA /* OnlineValidationState.swift in Sources */,
ED0C34381F2906EC00FAE9FD /* DefaultNetworkService+ActivityIndicator+Extension.swift in Sources */,
ED0C341E1F2906EC00FAE9FD /* Observable+Extensions.swift in Sources */,
ED0C34481F2906EC00FAE9FD /* CellTextFieldViewModel.swift in Sources */,
67B4E6EB206941CE00E233EA /* BiometricsService.swift in Sources */,
ED0C341A1F2906EC00FAE9FD /* ApiErrorProtocol.swift in Sources */,
ED0C34141F2906EC00FAE9FD /* BasePassCodeViewController.swift in Sources */,
ED0C342E1F2906EC00FAE9FD /* BasePassCodeService.swift in Sources */,
67B4E6F7206945DD00E233EA /* OnlineValidationResult.swift in Sources */,
ED0C340E1F2906EC00FAE9FD /* PassCodeHolder.swift in Sources */,
ED0C34461F2906EC00FAE9FD /* CellTextField.swift in Sources */,
ED0C34281F2906EC00FAE9FD /* CellFieldsToolBarProtocol.swift in Sources */,
ED69E7E81F2AC7CC00C74895 /* CellTextFieldToolBar.swift in Sources */,
ED0C342A1F2906EC00FAE9FD /* CellFieldValidationProtocol.swift in Sources */,
67B4E6F3206945D200E233EA /* BaseTextFieldViewModel.swift in Sources */,
ED0C34041F2906EC00FAE9FD /* ApiResponse.swift in Sources */,
ED0C34081F2906EC00FAE9FD /* LoadingBarButton.swift in Sources */,
ED0C34261F2906EC00FAE9FD /* CellFieldMaskProtocol.swift in Sources */,
ED0C34221F2906EC00FAE9FD /* UserDefaults+UserService.swift in Sources */,
ED0C34321F2906EC00FAE9FD /* CellFieldsJumpingService.swift in Sources */,
ED0C34121F2906EC00FAE9FD /* PassCodeValidationResult.swift in Sources */,
ED0C34061F2906EC00FAE9FD /* BaseDateFormatter.swift in Sources */,
ED0C34441F2906EC00FAE9FD /* ValidationService.swift in Sources */,

View File

@ -15,7 +15,7 @@ abstract_target 'LeadKitAdditions' do
use_frameworks!
pod "LeadKit", '~> 0.6.0'
pod 'LeadKit', :git => 'https://github.com/TouchInstinct/LeadKit', :branch => 'feature/text_field_view_model'
end
target 'LeadKitAdditions iOS Extensions' do
@ -23,7 +23,7 @@ abstract_target 'LeadKitAdditions' do
use_frameworks!
pod "LeadKit/Core-iOS-Extension", '~> 0.6.0'
pod "LeadKit/Core-iOS-Extension", :git => 'https://github.com/TouchInstinct/LeadKit', :branch => 'feature/text_field_view_model'
end
end

View File

@ -1,7 +1,7 @@
PODS:
- Alamofire (4.7.0)
- CocoaLumberjack/Default (3.3.0)
- CocoaLumberjack/Swift (3.3.0):
- CocoaLumberjack/Default (3.4.1)
- CocoaLumberjack/Swift (3.4.1):
- CocoaLumberjack/Default
- IDZSwiftCommonCrypto (0.10.0)
- InputMask (3.0.0)
@ -9,58 +9,68 @@ PODS:
- LeadKit (0.6.7):
- LeadKit/Core (= 0.6.7)
- LeadKit/Core (0.6.7):
- CocoaLumberjack/Swift (~> 3.3.0)
- ObjectMapper (~> 3.0.0)
- RxAlamofire (= 4.0.0)
- RxCocoa (= 4.0.0)
- RxSwift (= 4.0.0)
- TableKit (~> 2.5.0)
- CocoaLumberjack/Swift (~> 3.4)
- ObjectMapper (~> 3.0)
- RxAlamofire (~> 4.1)
- RxCocoa (~> 4.1)
- RxSwift (~> 4.1)
- TableKit (~> 2.6)
- UIScrollView-InfiniteScroll (~> 1.0.0)
- LeadKit/Core-iOS-Extension (0.6.7):
- CocoaLumberjack/Swift (~> 3.3.0)
- ObjectMapper (~> 3.0.0)
- RxAlamofire (= 4.0.0)
- RxCocoa (= 4.0.0)
- RxSwift (= 4.0.0)
- ObjectMapper (3.0.0)
- RxAlamofire (4.0.0):
- RxAlamofire/Core (= 4.0.0)
- RxAlamofire/Core (4.0.0):
- CocoaLumberjack/Swift (~> 3.4)
- ObjectMapper (~> 3.0)
- RxAlamofire (~> 4.1)
- RxCocoa (~> 4.1)
- RxSwift (~> 4.1)
- ObjectMapper (3.1.0)
- RxAlamofire (4.1.0):
- RxAlamofire/Core (= 4.1.0)
- RxAlamofire/Core (4.1.0):
- Alamofire (~> 4.5)
- RxSwift (~> 4.0)
- RxCocoa (4.0.0):
- RxCocoa (4.1.2):
- RxSwift (~> 4.0)
- RxSwift (4.0.0)
- RxSwift (4.1.2)
- SwiftLint (0.25.0)
- SwiftValidator (5.0.0)
- TableKit (2.5.0)
- TableKit (2.6.0)
- UIScrollView-InfiniteScroll (1.0.2)
DEPENDENCIES:
- IDZSwiftCommonCrypto
- InputMask (= 3.0.0)
- KeychainAccess (= 3.1.0)
- LeadKit (~> 0.6.0)
- LeadKit/Core-iOS-Extension (~> 0.6.0)
- LeadKit (from `https://github.com/TouchInstinct/LeadKit`, branch `feature/text_field_view_model`)
- LeadKit/Core-iOS-Extension (from `https://github.com/TouchInstinct/LeadKit`, branch `feature/text_field_view_model`)
- SwiftLint (~> 0.25)
- SwiftValidator (= 5.0.0)
EXTERNAL SOURCES:
LeadKit:
:branch: feature/text_field_view_model
:git: https://github.com/TouchInstinct/LeadKit
CHECKOUT OPTIONS:
LeadKit:
:commit: 463279d2865b2e77bd727e18d7bc9793c9539160
:git: https://github.com/TouchInstinct/LeadKit
SPEC CHECKSUMS:
Alamofire: 907e0a98eb68cdb7f9d1f541a563d6ac5dc77b25
CocoaLumberjack: 3c8c74683302f9012bb168e1c4b7ae3c0b558431
CocoaLumberjack: 2e258a064cacc8eb9a2aca318e24d02a0a7fd56d
IDZSwiftCommonCrypto: 4eef2c46e262dfbcbc1fd76365e066336680ad7d
InputMask: 37c273bde6705187d80cf0b4240cb42ea92096c3
KeychainAccess: 94c5540b32eabf7bc32bfb976a268e8ea05fd6da
LeadKit: 7d84bb111e7b6aca0c5d3ac5aee6f99d375d94d4
ObjectMapper: 92230db59bf8f341a5c3a3cf0b9fbdde3cf0d87f
RxAlamofire: 6ea579ac53bf14cb4bc7049a3866e5a769989b1d
RxCocoa: d62846ca96495d862fa4c59ea7d87e5031d7340e
RxSwift: fd680d75283beb5e2559486f3c0ff852f0d35334
LeadKit: d6dd4ec58e535c3a76cbc78b53d283278f61cbfa
ObjectMapper: 20505058f54e5c3ca69e1d6de9897d152a5369a6
RxAlamofire: 96a2bff4694a1609bb59c57b53d99ea7a0ddc64a
RxCocoa: d88ba0f1f6abf040011a9eb4b539324fc426843a
RxSwift: e49536837d9901277638493ea537394d4b55f570
SwiftLint: e14651157288e9e01d6e1a71db7014fb5744a8ea
SwiftValidator: 46cdd2061962df3ee8bab3c536dea9b34191d459
TableKit: 42d4dff2944f273cdeec2ef6352064eb6a9a355b
TableKit: 61880e4c13ac0ba396a308fcb1ae48f6dec8b458
UIScrollView-InfiniteScroll: c132d6d5851daff229ab4a1060ccf70a05a051c9
PODFILE CHECKSUM: d2f39766e2e1169f9216c0dc43b52873927b77cc
PODFILE CHECKSUM: d35945b0ded474b18dc52df4f9b12cb7fdf59377
COCOAPODS: 1.4.0

View File

@ -0,0 +1,169 @@
//
// 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 LeadKit
import RxSwift
import RxCocoa
/// Base implementation of TextFieldViewEvents.
open class BaseTextFieldViewEvents: TextFieldViewEvents {
public let textChangedDriver: Driver<String?>
/// Memberwise initializer.
///
/// - Parameter textChangedDriver: Driver that emits text changes from a view.
public init(textChangedDriver: Driver<String?>) {
self.textChangedDriver = textChangedDriver
}
}
/// Base implementation of text field view model events.
open class BaseTextFieldViewModelEvents: TextFieldViewModelEvents {
public let setTextDriver: Driver<String?>
public let changeValidationStateDriver: Driver<ValidationItemState>
public let changeOnlineValidationStateDriver: Driver<OnlineValidationState>
/// Memberwise initializer.
///
/// - Parameters:
/// - setTextDriver: Driver that emit text that should be set inside a view.
/// - changeValidationStateDriver: Driver that emit validation state changes events.
/// - changeOnlineValidationStateDriver: Driver that emit online validation state changes events.
public init(setTextDriver: Driver<String?>,
changeValidationStateDriver: Driver<ValidationItemState>,
changeOnlineValidationStateDriver: Driver<OnlineValidationState>) {
self.setTextDriver = setTextDriver
self.changeValidationStateDriver = changeValidationStateDriver
self.changeOnlineValidationStateDriver = changeOnlineValidationStateDriver
}
}
import SwiftValidator
public extension BaseTextFieldViewModelEvents {
/// Method that binds text driver to validation service via validation rules.
///
/// - Parameters:
/// - textDriver: Driver that emits text changes.
/// - rules: Rules to validate for.
/// - validationService: Validation service to register in.
/// - Returns: Driver that emit validation state changes.
static func offlineValidationDriver(with textDriver: Driver<String?>,
using rules: [Rule] = [RequiredRule()],
in validationService: ValidationService) -> Driver<ValidationItemState> {
let validationItem = ValidationItem(rules: rules, textDriver: textDriver)
validationService.register(item: validationItem)
let validationStateDriver = validationItem
.validationStateObservable
.asDriver(onErrorJustReturn: .initial)
return validationStateDriver
}
typealias OnlineValidationClosure = (String) -> Single<OnlineValidationResult>
/// Method that binds text driver to validation chain (offline validation -> online validation)
/// and returns online validation state driver.
///
/// - Parameters:
/// - textDriver: Driver that emits text changes.
/// - offlineRules: Rules to validate before online validation will be requested.
/// - validationClosure: Closure that will be called for online validation request.
/// - Returns: Driver that emit online validation state changes.
static func onlineValidationDriver(with textDriver: Driver<String?>,
using offlineRules: [Rule] = [],
validationClosure: @escaping OnlineValidationClosure) -> Driver<OnlineValidationState> {
return textDriver.flatMap { string -> Driver<OnlineValidationState> in
guard let nonEmptyString = string, !nonEmptyString.isEmpty else {
return .just(.initial)
}
let passedRules = offlineRules
.map { $0.validate(nonEmptyString) }
.reduce(true) { $0 && $1 }
guard passedRules else {
return .just(.initial)
}
let validationDriver = validationClosure(nonEmptyString).map { result -> OnlineValidationState in
if result.isValid {
return .valid
} else {
return .invalid(error: result.error)
}
}
.asDriver(onErrorJustReturn: .initial)
return Driver.merge([.just(.initial), .just(.processing), validationDriver])
}
}
/// Convenience initializer with offline and online validation.
///
/// - Parameters:
/// - binding: Data model field binding.
/// - rules: Rules to validate before online validation will be requested.
/// - validationService: Validation service to register in.
/// - onlineValidationClosure: Closure that will be called for online validation request.
/// - onlineValidationThrottle: Throttling duration for each text change.
convenience init<T>(binding: DataModelFieldBinding<T>,
rules: [Rule] = [RequiredRule()],
validationService: ValidationService,
onlineValidationClosure: OnlineValidationClosure? = nil,
onlineValidationThrottle: RxTimeInterval = 0.5) {
let dataModelFieldDriver = binding.fieldDriver
let offlineValidationDriver = BaseTextFieldViewModelEvents.offlineValidationDriver(with: dataModelFieldDriver,
using: rules,
in: validationService)
let onlineValidationDriver: Driver<OnlineValidationState>
if let onlineValidationClosure = onlineValidationClosure {
let throttledTextDriver = dataModelFieldDriver.throttle(onlineValidationThrottle)
onlineValidationDriver = BaseTextFieldViewModelEvents
.onlineValidationDriver(with: throttledTextDriver,
using: rules,
validationClosure: onlineValidationClosure)
} else {
onlineValidationDriver = .just(.initial)
}
self.init(setTextDriver: dataModelFieldDriver,
changeValidationStateDriver: offlineValidationDriver,
changeOnlineValidationStateDriver: onlineValidationDriver)
}
}

View File

@ -0,0 +1,39 @@
//
// 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 RxSwift
public extension BaseTextFieldViewEvents {
/// Convenience init with UITextField as textChangedDriver.
///
/// - Parameter textField: UITextField to use for text events.
convenience init(textField: UITextField) {
let textChangedDriver = textField.rx
.text
.asDriver()
.distinctUntilChanged { $0 == $1 }
self.init(textChangedDriver: textChangedDriver)
}
}

View File

@ -1,38 +0,0 @@
import RxSwift
import RxCocoa
import UIKit
typealias ItemSettingsBlock<UIItem> = (UIItem) -> Void where UIItem: UIView
protocol CellFieldJumpingProtocol: FormCellViewModelProtocol {
var toolBar: UIToolbar? { get set }
var shouldGoForward: PublishSubject<Void> { get }
var shouldBecomeFirstResponder: PublishSubject<Void> { get }
var shouldResignFirstResponder: PublishSubject<Void> { get }
var returnButtonType: UIReturnKeyType { get set }
}
extension CellFieldJumpingProtocol {
func bind(for textField: UITextField, to disposeBag: DisposeBag) {
shouldResignFirstResponder.asObservable()
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak textField] _ in
textField?.resignFirstResponder()
})
.disposed(by: disposeBag)
shouldBecomeFirstResponder.asObservable()
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak textField] _ in
textField?.becomeFirstResponder()
})
.disposed(by: disposeBag)
}
}

View File

@ -1,14 +0,0 @@
protocol CellFieldMaskProtocol {
var haveMask: Bool { get }
var maskFieldTextProxy: MaskFieldTextProxy? { get set }
}
extension CellFieldMaskProtocol {
var haveMask: Bool {
return maskFieldTextProxy != nil
}
}

View File

@ -1,5 +0,0 @@
protocol CellFieldValidationProtocol {
var validationItem: ValidationItem? { get set }
}

View File

@ -1,16 +0,0 @@
import UIKit
import RxSwift
protocol CellFieldsToolBarProtocol: class {
var needArrows: Bool { get set }
var canGoForward: Bool { get set }
var canGoBackward: Bool { get set }
var shouldGoForward: PublishSubject<Void> { get }
var shouldGoBackward: PublishSubject<Void> { get }
var shouldEndEditing: PublishSubject<Void> { get }
}

View File

@ -1,15 +0,0 @@
import RxCocoa
import RxSwift
protocol FormCellViewModelProtocol: class {
var isActive: Bool { get set }
}
extension FormCellViewModelProtocol {
func activate(_ isActive: Bool) -> Self {
self.isActive = isActive
return self
}
}

View File

@ -0,0 +1,34 @@
//
// 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 Foundation
/// Prototol with two fields that describes result of online validation.
public protocol OnlineValidationResult {
/// Contains true if online validation did passed.
var isValid: Bool { get }
/// May contain an error if validation did failed.
var error: Error? { get }
}

View File

@ -1,138 +0,0 @@
import RxSwift
import UIKit
struct CellFieldsJumpingServiceConfig {
var toolBarNeedArrows = true
init() {}
static var `default`: CellFieldsJumpingServiceConfig {
return CellFieldsJumpingServiceConfig()
}
}
class CellFieldsJumpingService {
private var disposeBag = DisposeBag()
// MARK: - Private properties
private var cellFields: [CellFieldJumpingProtocol] = []
// MARK: - Public propertries
var config: CellFieldsJumpingServiceConfig = .default {
didSet {
configure()
}
}
let didDone = PublishSubject<Void>()
// MARK: - Initialization
init() {}
// MARK: - Public
func removeAll() {
cellFields.removeAll()
disposeBag = DisposeBag()
}
func add(fieled: CellFieldJumpingProtocol, shouldConfigure: Bool = true) {
add(fieleds: [fieled], shouldConfigure: shouldConfigure)
}
func add(fieleds: [CellFieldJumpingProtocol], shouldConfigure: Bool = true) {
cellFields += fieleds
if shouldConfigure {
configure()
}
}
func configure() {
disposeBag = DisposeBag()
let cellFields = self.cellFields
cellFields
.filter { $0.isActive }
.enumerated()
.forEach { offset, field in
field.toolBar = toolBar(for: field, with: offset)
field.returnButtonType = .next
field.shouldGoForward.asObservable()
.subscribe(onNext: { [weak self] in
self?.shouldGoForwardAction(from: offset)
})
.disposed(by: disposeBag)
}
cellFields.lastActive?.returnButtonType = .done
}
private func toolBar(for field: CellFieldJumpingProtocol, with index: Int) -> UIToolbar {
let toolBar = CellTextFieldToolBar()
toolBar.canGoForward = cellFields.nextActive(from: index) != nil
toolBar.canGoBackward = cellFields.previousActive(from: index) != nil
toolBar.needArrows = config.toolBarNeedArrows
toolBar.shouldGoForward.asObservable()
.subscribe(onNext: { [weak self] in
self?.shouldGoForwardAction(from: index)
})
.disposed(by: disposeBag)
toolBar.shouldGoBackward
.subscribe(onNext: { [weak self] in
if let previousActive = self?.cellFields.previousActive(from: index) {
previousActive.shouldBecomeFirstResponder.onNext(Void())
}
})
.disposed(by: disposeBag)
toolBar.shouldEndEditing
.subscribe(onNext: { [field] in
field.shouldResignFirstResponder.onNext(Void())
})
.disposed(by: disposeBag)
return toolBar
}
private func shouldGoForwardAction(from index: Int) {
if let nextActive = cellFields.nextActive(from: index) {
nextActive.shouldBecomeFirstResponder.onNext(Void())
} else {
didDone.onNext(Void())
}
}
}
extension Array where Element == CellFieldJumpingProtocol {
var firstActive: CellFieldJumpingProtocol? {
return first { $0.isActive }
}
var lastActive: CellFieldJumpingProtocol? {
return reversed().first { $0.isActive }
}
func nextActive(from index: Int) -> CellFieldJumpingProtocol? {
return enumerated().first { $0 > index && $1.isActive }?.element
}
func previousActive(from index: Int) -> CellFieldJumpingProtocol? {
let reversedIndex = count - index - 1
return reversed().enumerated().first { $0 > reversedIndex && $1.isActive }?.element
}
}

View File

@ -0,0 +1,36 @@
//
// 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.
//
/// Enum that describes current state of online validation.
///
/// - initial: Nothing did happen.
/// - processing: Processing validation.
/// - valid: Got a valid result.
/// - invalid: Got an invalid result.
public enum OnlineValidationState {
case initial
case processing
case valid
case invalid(error: Error?)
}

View File

@ -1,46 +0,0 @@
import UIKit
import RxCocoa
import RxSwift
class CellTextField: UITextField {
private var disposeBag = DisposeBag()
var viewModel: CellTextFieldViewModel? {
didSet {
configure()
}
}
// MARK: - Init
private func configure() {
disposeBag = DisposeBag()
guard let viewModel = viewModel else {
return
}
inputAccessoryView = viewModel.toolBar
returnKeyType = viewModel.returnButtonType
text = viewModel.textValue
placeholder = viewModel.placeholder
viewModel.textFieldSettingsBlock?(self)
viewModel.bind(for: self, to: disposeBag)
rx.text.asDriver()
.drive(onNext: {
viewModel.setTextValue($0)
})
.disposed(by: disposeBag)
rx.controlEvent(.editingDidEndOnExit)
.subscribe(onNext: { [viewModel] in
viewModel.shouldGoForward.onNext(Void())
})
.disposed(by: disposeBag)
}
}

View File

@ -1,41 +0,0 @@
import UIKit
import RxSwift
class CellTextFieldViewModel: CellFieldJumpingProtocol {
private let text: Variable<String?>
let placeholder: String
let textFieldSettingsBlock: ItemSettingsBlock<UITextField>?
// MARK: - CellFieldJumpingProtocol
var toolBar: UIToolbar?
let shouldGoForward = PublishSubject<Void>()
let shouldBecomeFirstResponder = PublishSubject<Void>()
let shouldResignFirstResponder = PublishSubject<Void>()
var returnButtonType: UIReturnKeyType = .default
var isActive: Bool = true
init(initialText: String = "", placeholder: String = "", textFieldSettingsBlock: ItemSettingsBlock<UITextField>? = nil) {
text = Variable(initialText)
self.placeholder = placeholder
self.textFieldSettingsBlock = textFieldSettingsBlock
}
// MARK: - Internal
var textValue: String? {
return text.value
}
func setTextValue(_ value: String?) {
text.value = value
}
}

View File

@ -1,107 +0,0 @@
import UIKit
import RxSwift
import RxCocoa
import LeadKit
class CellTextFieldToolBar: UIToolbar, CellFieldsToolBarProtocol {
private let buttonSpace: CGFloat = 20
// MARK: - CellFieldsToolBarProtocol
var needArrows: Bool = true
var canGoForward: Bool = false {
didSet {
forwardButton.isEnabled = canGoForward
}
}
var canGoBackward: Bool = false {
didSet {
backButton.isEnabled = canGoBackward
}
}
var shouldGoForward = PublishSubject<Void>()
var shouldGoBackward = PublishSubject<Void>()
var shouldEndEditing = PublishSubject<Void>()
// MARK: - UIBarButtonItems
var backButtonImage: UIImage? {
didSet {
backButton.image = backButtonImage
}
}
var forwardButtonImage: UIImage? {
didSet {
backButton.image = backButtonImage
}
}
private(set) lazy var backButton: UIBarButtonItem = {
let backButton = UIBarButtonItem(image: self.backButtonImage,
style: .plain,
target: self,
action: #selector(backAction))
return backButton
}()
private(set) lazy var forwardButton: UIBarButtonItem = {
let forwardButton = UIBarButtonItem(image: self.forwardButtonImage,
style: .plain,
target: self,
action: #selector(forwardAction))
return forwardButton
}()
private(set) lazy var closeButton: UIBarButtonItem = {
let doneButton = UIBarButtonItem(barButtonSystemItem: .done,
target: self,
action: #selector(doneAction))
return doneButton
}()
// MARK: - Initialization
override init(frame: CGRect) {
super.init(frame: frame)
initialization()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initialization()
}
private func initialization() {
barStyle = .default
isTranslucent = true
tintColor = UIColor(hex6: 0x0A84DF)
sizeToFit()
let leftSpacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let firstButtonsSpacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
firstButtonsSpacer.width = buttonSpace
let secondButtonsSpacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
secondButtonsSpacer.width = buttonSpace
setItems([leftSpacer, backButton, firstButtonsSpacer, forwardButton, secondButtonsSpacer, closeButton], animated: true)
items?.forEach { $0.tintColor = tintColor }
}
// MARK: - Actions
@objc private func backAction() {
shouldGoBackward.onNext(Void())
}
@objc private func forwardAction() {
shouldGoForward.onNext(Void())
}
@objc private func doneAction() {
shouldEndEditing.onNext(Void())
}
}