├── .github └── stale.yml ├── .gitignore ├── Example ├── KWVerificationCodeView.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── KWVerificationCodeView-Example.xcscheme ├── KWVerificationCodeView.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── KWVerificationCodeView │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ └── kw-logo-mark.png │ ├── Info.plist │ ├── ProgramaticalVerificationCodeViewController.swift │ └── VerificationCodeViewController.swift ├── Podfile ├── Podfile.lock └── Tests │ ├── Info.plist │ └── Tests.swift ├── KWVerificationCodeView.podspec ├── KWVerificationCodeView ├── 0.5.0 │ └── KWVerificationCodeView.podspec ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── Extensions │ ├── StringExtension.swift │ └── UIViewExtension.swift │ ├── KWTextFieldView.swift │ ├── KWTextFieldView.xib │ ├── KWVerificationCodeView.swift │ └── KWVerificationCodeView.xib ├── LICENSE ├── README.md ├── Screenshots ├── KWVerificationCodeView.gif ├── interfacebuilder.png └── screenshot.png └── logo.png /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 30 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - bug 8 | - enhancement 9 | - feature-request 10 | # Label to use when marking an issue as stale 11 | staleLabel: stale 12 | # Comment to post when marking an issue as stale. Set to `false` to disable 13 | markComment: > 14 | This issue has been automatically marked as stale because it has not had 15 | recent activity. It will be closed if no further activity occurs. Thank you 16 | for your contributions. 17 | # Comment to post when closing a stale issue. Set to `false` to disable 18 | closeComment: false 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | Carthage 26 | Pods/ -------------------------------------------------------------------------------- /Example/KWVerificationCodeView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 53; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2CA88CD58398C2B419E9B36C /* Pods_KWVerificationCodeView_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C68BD3F967305D340EA20FFD /* Pods_KWVerificationCodeView_Tests.framework */; }; 11 | 2DB200677C25A654990BA580 /* Pods_KWVerificationCodeView_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29FC60609011D27ACC17DB2A /* Pods_KWVerificationCodeView_Example.framework */; }; 12 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 13 | 607FACD81AFB9204008FA782 /* VerificationCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* VerificationCodeViewController.swift */; }; 14 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 15 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 16 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 17 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; 18 | D1AA5A4D20D0FD7B007FE474 /* ProgramaticalVerificationCodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1AA5A4C20D0FD7B007FE474 /* ProgramaticalVerificationCodeViewController.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 27 | remoteInfo = KWVerificationCodeView; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | 29FC60609011D27ACC17DB2A /* Pods_KWVerificationCodeView_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_KWVerificationCodeView_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 423112B5C6F551741EC3F015 /* Pods-KWVerificationCodeView_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KWVerificationCodeView_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-KWVerificationCodeView_Tests/Pods-KWVerificationCodeView_Tests.debug.xcconfig"; sourceTree = ""; }; 34 | 607FACD01AFB9204008FA782 /* KWVerificationCodeView_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KWVerificationCodeView_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 36 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 37 | 607FACD71AFB9204008FA782 /* VerificationCodeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VerificationCodeViewController.swift; sourceTree = ""; }; 38 | 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 39 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 40 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 41 | 607FACE51AFB9204008FA782 /* KWVerificationCodeView_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KWVerificationCodeView_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 44 | 7DA49E735ED3B0C245F0B8C7 /* Pods-KWVerificationCodeView_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KWVerificationCodeView_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-KWVerificationCodeView_Example/Pods-KWVerificationCodeView_Example.release.xcconfig"; sourceTree = ""; }; 45 | 8F723ADDC751FC9CC3C9BE34 /* Pods-KWVerificationCodeView_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KWVerificationCodeView_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-KWVerificationCodeView_Tests/Pods-KWVerificationCodeView_Tests.release.xcconfig"; sourceTree = ""; }; 46 | C3C8FC4284D4530532E3C9FB /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 47 | C68BD3F967305D340EA20FFD /* Pods_KWVerificationCodeView_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_KWVerificationCodeView_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | D1AA5A4C20D0FD7B007FE474 /* ProgramaticalVerificationCodeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgramaticalVerificationCodeViewController.swift; sourceTree = ""; }; 49 | D51BF4885572F8FECD1E4AF7 /* Pods-KWVerificationCodeView_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KWVerificationCodeView_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-KWVerificationCodeView_Example/Pods-KWVerificationCodeView_Example.debug.xcconfig"; sourceTree = ""; }; 50 | E6C0C121AF93D56E0FE9F947 /* KWVerificationCodeView.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = KWVerificationCodeView.podspec; path = ../KWVerificationCodeView.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 51 | F538A5E79FE77B8D323F9B7B /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | 2DB200677C25A654990BA580 /* Pods_KWVerificationCodeView_Example.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | 2CA88CD58398C2B419E9B36C /* Pods_KWVerificationCodeView_Tests.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXFrameworksBuildPhase section */ 72 | 73 | /* Begin PBXGroup section */ 74 | 5BDB25E32F432AA3094DB5BE /* Pods */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | D51BF4885572F8FECD1E4AF7 /* Pods-KWVerificationCodeView_Example.debug.xcconfig */, 78 | 7DA49E735ED3B0C245F0B8C7 /* Pods-KWVerificationCodeView_Example.release.xcconfig */, 79 | 423112B5C6F551741EC3F015 /* Pods-KWVerificationCodeView_Tests.debug.xcconfig */, 80 | 8F723ADDC751FC9CC3C9BE34 /* Pods-KWVerificationCodeView_Tests.release.xcconfig */, 81 | ); 82 | name = Pods; 83 | sourceTree = ""; 84 | }; 85 | 607FACC71AFB9204008FA782 = { 86 | isa = PBXGroup; 87 | children = ( 88 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 89 | 607FACD21AFB9204008FA782 /* Example */, 90 | 607FACE81AFB9204008FA782 /* Tests */, 91 | 607FACD11AFB9204008FA782 /* Products */, 92 | 5BDB25E32F432AA3094DB5BE /* Pods */, 93 | E557B51C92254B3511274B3D /* Frameworks */, 94 | ); 95 | sourceTree = ""; 96 | }; 97 | 607FACD11AFB9204008FA782 /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 607FACD01AFB9204008FA782 /* KWVerificationCodeView_Example.app */, 101 | 607FACE51AFB9204008FA782 /* KWVerificationCodeView_Tests.xctest */, 102 | ); 103 | name = Products; 104 | sourceTree = ""; 105 | }; 106 | 607FACD21AFB9204008FA782 /* Example */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 110 | 607FACD71AFB9204008FA782 /* VerificationCodeViewController.swift */, 111 | D1AA5A4C20D0FD7B007FE474 /* ProgramaticalVerificationCodeViewController.swift */, 112 | 607FACD91AFB9204008FA782 /* Main.storyboard */, 113 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 114 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 115 | 607FACD31AFB9204008FA782 /* Supporting Files */, 116 | ); 117 | name = Example; 118 | path = KWVerificationCodeView; 119 | sourceTree = ""; 120 | }; 121 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 607FACD41AFB9204008FA782 /* Info.plist */, 125 | ); 126 | name = "Supporting Files"; 127 | sourceTree = ""; 128 | }; 129 | 607FACE81AFB9204008FA782 /* Tests */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 607FACEB1AFB9204008FA782 /* Tests.swift */, 133 | 607FACE91AFB9204008FA782 /* Supporting Files */, 134 | ); 135 | path = Tests; 136 | sourceTree = ""; 137 | }; 138 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 607FACEA1AFB9204008FA782 /* Info.plist */, 142 | ); 143 | name = "Supporting Files"; 144 | sourceTree = ""; 145 | }; 146 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | E6C0C121AF93D56E0FE9F947 /* KWVerificationCodeView.podspec */, 150 | F538A5E79FE77B8D323F9B7B /* README.md */, 151 | C3C8FC4284D4530532E3C9FB /* LICENSE */, 152 | ); 153 | name = "Podspec Metadata"; 154 | sourceTree = ""; 155 | }; 156 | E557B51C92254B3511274B3D /* Frameworks */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 29FC60609011D27ACC17DB2A /* Pods_KWVerificationCodeView_Example.framework */, 160 | C68BD3F967305D340EA20FFD /* Pods_KWVerificationCodeView_Tests.framework */, 161 | ); 162 | name = Frameworks; 163 | sourceTree = ""; 164 | }; 165 | /* End PBXGroup section */ 166 | 167 | /* Begin PBXNativeTarget section */ 168 | 607FACCF1AFB9204008FA782 /* KWVerificationCodeView_Example */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "KWVerificationCodeView_Example" */; 171 | buildPhases = ( 172 | 8A96BB52F0E82B4C4B2EC0C9 /* [CP] Check Pods Manifest.lock */, 173 | 607FACCC1AFB9204008FA782 /* Sources */, 174 | 607FACCD1AFB9204008FA782 /* Frameworks */, 175 | 607FACCE1AFB9204008FA782 /* Resources */, 176 | 577FAF386CE51F89750D85AF /* [CP] Embed Pods Frameworks */, 177 | ); 178 | buildRules = ( 179 | ); 180 | dependencies = ( 181 | ); 182 | name = KWVerificationCodeView_Example; 183 | productName = KWVerificationCodeView; 184 | productReference = 607FACD01AFB9204008FA782 /* KWVerificationCodeView_Example.app */; 185 | productType = "com.apple.product-type.application"; 186 | }; 187 | 607FACE41AFB9204008FA782 /* KWVerificationCodeView_Tests */ = { 188 | isa = PBXNativeTarget; 189 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "KWVerificationCodeView_Tests" */; 190 | buildPhases = ( 191 | C416736B908F6E6989465549 /* [CP] Check Pods Manifest.lock */, 192 | 607FACE11AFB9204008FA782 /* Sources */, 193 | 607FACE21AFB9204008FA782 /* Frameworks */, 194 | 607FACE31AFB9204008FA782 /* Resources */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */, 200 | ); 201 | name = KWVerificationCodeView_Tests; 202 | productName = Tests; 203 | productReference = 607FACE51AFB9204008FA782 /* KWVerificationCodeView_Tests.xctest */; 204 | productType = "com.apple.product-type.bundle.unit-test"; 205 | }; 206 | /* End PBXNativeTarget section */ 207 | 208 | /* Begin PBXProject section */ 209 | 607FACC81AFB9204008FA782 /* Project object */ = { 210 | isa = PBXProject; 211 | attributes = { 212 | BuildIndependentTargetsInParallel = YES; 213 | LastSwiftUpdateCheck = 0720; 214 | LastUpgradeCheck = 1430; 215 | ORGANIZATIONNAME = CocoaPods; 216 | TargetAttributes = { 217 | 607FACCF1AFB9204008FA782 = { 218 | CreatedOnToolsVersion = 6.3.1; 219 | LastSwiftMigration = 1020; 220 | }; 221 | 607FACE41AFB9204008FA782 = { 222 | CreatedOnToolsVersion = 6.3.1; 223 | LastSwiftMigration = 1020; 224 | TestTargetID = 607FACCF1AFB9204008FA782; 225 | }; 226 | }; 227 | }; 228 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "KWVerificationCodeView" */; 229 | compatibilityVersion = "Xcode 3.2"; 230 | developmentRegion = English; 231 | hasScannedForEncodings = 0; 232 | knownRegions = ( 233 | English, 234 | en, 235 | Base, 236 | ); 237 | mainGroup = 607FACC71AFB9204008FA782; 238 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 239 | projectDirPath = ""; 240 | projectRoot = ""; 241 | targets = ( 242 | 607FACCF1AFB9204008FA782 /* KWVerificationCodeView_Example */, 243 | 607FACE41AFB9204008FA782 /* KWVerificationCodeView_Tests */, 244 | ); 245 | }; 246 | /* End PBXProject section */ 247 | 248 | /* Begin PBXResourcesBuildPhase section */ 249 | 607FACCE1AFB9204008FA782 /* Resources */ = { 250 | isa = PBXResourcesBuildPhase; 251 | buildActionMask = 2147483647; 252 | files = ( 253 | 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, 254 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 255 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | 607FACE31AFB9204008FA782 /* Resources */ = { 260 | isa = PBXResourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | /* End PBXResourcesBuildPhase section */ 267 | 268 | /* Begin PBXShellScriptBuildPhase section */ 269 | 577FAF386CE51F89750D85AF /* [CP] Embed Pods Frameworks */ = { 270 | isa = PBXShellScriptBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | ); 274 | inputPaths = ( 275 | "${PODS_ROOT}/Target Support Files/Pods-KWVerificationCodeView_Example/Pods-KWVerificationCodeView_Example-frameworks.sh", 276 | "${BUILT_PRODUCTS_DIR}/KWVerificationCodeView/KWVerificationCodeView.framework", 277 | ); 278 | name = "[CP] Embed Pods Frameworks"; 279 | outputPaths = ( 280 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/KWVerificationCodeView.framework", 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | shellPath = /bin/sh; 284 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-KWVerificationCodeView_Example/Pods-KWVerificationCodeView_Example-frameworks.sh\"\n"; 285 | showEnvVarsInLog = 0; 286 | }; 287 | 8A96BB52F0E82B4C4B2EC0C9 /* [CP] Check Pods Manifest.lock */ = { 288 | isa = PBXShellScriptBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | ); 292 | inputPaths = ( 293 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 294 | "${PODS_ROOT}/Manifest.lock", 295 | ); 296 | name = "[CP] Check Pods Manifest.lock"; 297 | outputPaths = ( 298 | "$(DERIVED_FILE_DIR)/Pods-KWVerificationCodeView_Example-checkManifestLockResult.txt", 299 | ); 300 | runOnlyForDeploymentPostprocessing = 0; 301 | shellPath = /bin/sh; 302 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 303 | showEnvVarsInLog = 0; 304 | }; 305 | C416736B908F6E6989465549 /* [CP] Check Pods Manifest.lock */ = { 306 | isa = PBXShellScriptBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | inputPaths = ( 311 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 312 | "${PODS_ROOT}/Manifest.lock", 313 | ); 314 | name = "[CP] Check Pods Manifest.lock"; 315 | outputPaths = ( 316 | "$(DERIVED_FILE_DIR)/Pods-KWVerificationCodeView_Tests-checkManifestLockResult.txt", 317 | ); 318 | runOnlyForDeploymentPostprocessing = 0; 319 | shellPath = /bin/sh; 320 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 321 | showEnvVarsInLog = 0; 322 | }; 323 | /* End PBXShellScriptBuildPhase section */ 324 | 325 | /* Begin PBXSourcesBuildPhase section */ 326 | 607FACCC1AFB9204008FA782 /* Sources */ = { 327 | isa = PBXSourcesBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | 607FACD81AFB9204008FA782 /* VerificationCodeViewController.swift in Sources */, 331 | D1AA5A4D20D0FD7B007FE474 /* ProgramaticalVerificationCodeViewController.swift in Sources */, 332 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | 607FACE11AFB9204008FA782 /* Sources */ = { 337 | isa = PBXSourcesBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, 341 | ); 342 | runOnlyForDeploymentPostprocessing = 0; 343 | }; 344 | /* End PBXSourcesBuildPhase section */ 345 | 346 | /* Begin PBXTargetDependency section */ 347 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { 348 | isa = PBXTargetDependency; 349 | target = 607FACCF1AFB9204008FA782 /* KWVerificationCodeView_Example */; 350 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; 351 | }; 352 | /* End PBXTargetDependency section */ 353 | 354 | /* Begin PBXVariantGroup section */ 355 | 607FACD91AFB9204008FA782 /* Main.storyboard */ = { 356 | isa = PBXVariantGroup; 357 | children = ( 358 | 607FACDA1AFB9204008FA782 /* Base */, 359 | ); 360 | name = Main.storyboard; 361 | sourceTree = ""; 362 | }; 363 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 364 | isa = PBXVariantGroup; 365 | children = ( 366 | 607FACDF1AFB9204008FA782 /* Base */, 367 | ); 368 | name = LaunchScreen.xib; 369 | sourceTree = ""; 370 | }; 371 | /* End PBXVariantGroup section */ 372 | 373 | /* Begin XCBuildConfiguration section */ 374 | 607FACED1AFB9204008FA782 /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | ALWAYS_SEARCH_USER_PATHS = NO; 378 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 379 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 380 | CLANG_CXX_LIBRARY = "libc++"; 381 | CLANG_ENABLE_MODULES = YES; 382 | CLANG_ENABLE_OBJC_ARC = YES; 383 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 384 | CLANG_WARN_BOOL_CONVERSION = YES; 385 | CLANG_WARN_COMMA = YES; 386 | CLANG_WARN_CONSTANT_CONVERSION = YES; 387 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 388 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 389 | CLANG_WARN_EMPTY_BODY = YES; 390 | CLANG_WARN_ENUM_CONVERSION = YES; 391 | CLANG_WARN_INFINITE_RECURSION = YES; 392 | CLANG_WARN_INT_CONVERSION = YES; 393 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 394 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 395 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 396 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 397 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 398 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 399 | CLANG_WARN_STRICT_PROTOTYPES = YES; 400 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 401 | CLANG_WARN_UNREACHABLE_CODE = YES; 402 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 403 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 404 | COPY_PHASE_STRIP = NO; 405 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 406 | ENABLE_STRICT_OBJC_MSGSEND = YES; 407 | ENABLE_TESTABILITY = YES; 408 | GCC_C_LANGUAGE_STANDARD = gnu99; 409 | GCC_DYNAMIC_NO_PIC = NO; 410 | GCC_NO_COMMON_BLOCKS = YES; 411 | GCC_OPTIMIZATION_LEVEL = 0; 412 | GCC_PREPROCESSOR_DEFINITIONS = ( 413 | "DEBUG=1", 414 | "$(inherited)", 415 | ); 416 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 417 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 418 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 419 | GCC_WARN_UNDECLARED_SELECTOR = YES; 420 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 421 | GCC_WARN_UNUSED_FUNCTION = YES; 422 | GCC_WARN_UNUSED_VARIABLE = YES; 423 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 424 | MTL_ENABLE_DEBUG_INFO = YES; 425 | ONLY_ACTIVE_ARCH = YES; 426 | SDKROOT = iphoneos; 427 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 428 | SWIFT_VERSION = 4.0; 429 | }; 430 | name = Debug; 431 | }; 432 | 607FACEE1AFB9204008FA782 /* Release */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | ALWAYS_SEARCH_USER_PATHS = NO; 436 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 437 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 438 | CLANG_CXX_LIBRARY = "libc++"; 439 | CLANG_ENABLE_MODULES = YES; 440 | CLANG_ENABLE_OBJC_ARC = YES; 441 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 442 | CLANG_WARN_BOOL_CONVERSION = YES; 443 | CLANG_WARN_COMMA = YES; 444 | CLANG_WARN_CONSTANT_CONVERSION = YES; 445 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 446 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 447 | CLANG_WARN_EMPTY_BODY = YES; 448 | CLANG_WARN_ENUM_CONVERSION = YES; 449 | CLANG_WARN_INFINITE_RECURSION = YES; 450 | CLANG_WARN_INT_CONVERSION = YES; 451 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 452 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 453 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 454 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 455 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 456 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 457 | CLANG_WARN_STRICT_PROTOTYPES = YES; 458 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 459 | CLANG_WARN_UNREACHABLE_CODE = YES; 460 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 461 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 462 | COPY_PHASE_STRIP = NO; 463 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 464 | ENABLE_NS_ASSERTIONS = NO; 465 | ENABLE_STRICT_OBJC_MSGSEND = YES; 466 | GCC_C_LANGUAGE_STANDARD = gnu99; 467 | GCC_NO_COMMON_BLOCKS = YES; 468 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 469 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 470 | GCC_WARN_UNDECLARED_SELECTOR = YES; 471 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 472 | GCC_WARN_UNUSED_FUNCTION = YES; 473 | GCC_WARN_UNUSED_VARIABLE = YES; 474 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 475 | MTL_ENABLE_DEBUG_INFO = NO; 476 | SDKROOT = iphoneos; 477 | SWIFT_COMPILATION_MODE = wholemodule; 478 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 479 | SWIFT_VERSION = 4.0; 480 | VALIDATE_PRODUCT = YES; 481 | }; 482 | name = Release; 483 | }; 484 | 607FACF01AFB9204008FA782 /* Debug */ = { 485 | isa = XCBuildConfiguration; 486 | baseConfigurationReference = D51BF4885572F8FECD1E4AF7 /* Pods-KWVerificationCodeView_Example.debug.xcconfig */; 487 | buildSettings = { 488 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 489 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 490 | DEVELOPMENT_TEAM = ""; 491 | INFOPLIST_FILE = KWVerificationCodeView/Info.plist; 492 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 493 | LD_RUNPATH_SEARCH_PATHS = ( 494 | "$(inherited)", 495 | "@executable_path/Frameworks", 496 | ); 497 | MODULE_NAME = ExampleApp; 498 | PRODUCT_BUNDLE_IDENTIFIER = "com.keepworks.KWVerificationCodeView-Example"; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | SWIFT_VERSION = 5.0; 501 | TARGETED_DEVICE_FAMILY = 1; 502 | }; 503 | name = Debug; 504 | }; 505 | 607FACF11AFB9204008FA782 /* Release */ = { 506 | isa = XCBuildConfiguration; 507 | baseConfigurationReference = 7DA49E735ED3B0C245F0B8C7 /* Pods-KWVerificationCodeView_Example.release.xcconfig */; 508 | buildSettings = { 509 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 510 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 511 | DEVELOPMENT_TEAM = ""; 512 | INFOPLIST_FILE = KWVerificationCodeView/Info.plist; 513 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 514 | LD_RUNPATH_SEARCH_PATHS = ( 515 | "$(inherited)", 516 | "@executable_path/Frameworks", 517 | ); 518 | MODULE_NAME = ExampleApp; 519 | PRODUCT_BUNDLE_IDENTIFIER = "com.keepworks.KWVerificationCodeView-Example"; 520 | PRODUCT_NAME = "$(TARGET_NAME)"; 521 | SWIFT_VERSION = 5.0; 522 | TARGETED_DEVICE_FAMILY = 1; 523 | }; 524 | name = Release; 525 | }; 526 | 607FACF31AFB9204008FA782 /* Debug */ = { 527 | isa = XCBuildConfiguration; 528 | baseConfigurationReference = 423112B5C6F551741EC3F015 /* Pods-KWVerificationCodeView_Tests.debug.xcconfig */; 529 | buildSettings = { 530 | DEVELOPMENT_TEAM = ""; 531 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 532 | GCC_PREPROCESSOR_DEFINITIONS = ( 533 | "DEBUG=1", 534 | "$(inherited)", 535 | ); 536 | INFOPLIST_FILE = Tests/Info.plist; 537 | LD_RUNPATH_SEARCH_PATHS = ( 538 | "$(inherited)", 539 | "@executable_path/Frameworks", 540 | "@loader_path/Frameworks", 541 | ); 542 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 543 | PRODUCT_NAME = "$(TARGET_NAME)"; 544 | SWIFT_VERSION = 5.0; 545 | }; 546 | name = Debug; 547 | }; 548 | 607FACF41AFB9204008FA782 /* Release */ = { 549 | isa = XCBuildConfiguration; 550 | baseConfigurationReference = 8F723ADDC751FC9CC3C9BE34 /* Pods-KWVerificationCodeView_Tests.release.xcconfig */; 551 | buildSettings = { 552 | DEVELOPMENT_TEAM = ""; 553 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 554 | INFOPLIST_FILE = Tests/Info.plist; 555 | LD_RUNPATH_SEARCH_PATHS = ( 556 | "$(inherited)", 557 | "@executable_path/Frameworks", 558 | "@loader_path/Frameworks", 559 | ); 560 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 561 | PRODUCT_NAME = "$(TARGET_NAME)"; 562 | SWIFT_VERSION = 5.0; 563 | }; 564 | name = Release; 565 | }; 566 | /* End XCBuildConfiguration section */ 567 | 568 | /* Begin XCConfigurationList section */ 569 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "KWVerificationCodeView" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | 607FACED1AFB9204008FA782 /* Debug */, 573 | 607FACEE1AFB9204008FA782 /* Release */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | defaultConfigurationName = Release; 577 | }; 578 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "KWVerificationCodeView_Example" */ = { 579 | isa = XCConfigurationList; 580 | buildConfigurations = ( 581 | 607FACF01AFB9204008FA782 /* Debug */, 582 | 607FACF11AFB9204008FA782 /* Release */, 583 | ); 584 | defaultConfigurationIsVisible = 0; 585 | defaultConfigurationName = Release; 586 | }; 587 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "KWVerificationCodeView_Tests" */ = { 588 | isa = XCConfigurationList; 589 | buildConfigurations = ( 590 | 607FACF31AFB9204008FA782 /* Debug */, 591 | 607FACF41AFB9204008FA782 /* Release */, 592 | ); 593 | defaultConfigurationIsVisible = 0; 594 | defaultConfigurationName = Release; 595 | }; 596 | /* End XCConfigurationList section */ 597 | }; 598 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 599 | } 600 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView.xcodeproj/xcshareddata/xcschemes/KWVerificationCodeView-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 51 | 52 | 53 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 76 | 78 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // KWVerificationCodeView 4 | // 5 | // Created by KeepWorks on 01/10/2017. 6 | // Copyright (c) 2017 KeepWorks Technologies Pvt Ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | return true 18 | } 19 | 20 | func applicationWillResignActive(_ application: UIApplication) { 21 | } 22 | 23 | func applicationDidEnterBackground(_ application: UIApplication) { 24 | } 25 | 26 | func applicationWillEnterForeground(_ application: UIApplication) { 27 | } 28 | 29 | func applicationDidBecomeActive(_ application: UIApplication) { 30 | } 31 | 32 | func applicationWillTerminate(_ application: UIApplication) { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 63 | 69 | 75 | 82 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 157 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "filename" : "kw-logo-mark.png", 45 | "idiom" : "ios-marketing", 46 | "scale" : "1x", 47 | "size" : "1024x1024" 48 | } 49 | ], 50 | "info" : { 51 | "author" : "xcode", 52 | "version" : 1 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/Images.xcassets/AppIcon.appiconset/kw-logo-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keepworks/KWVerificationCodeView/9556739aae59865e37e2d9981e680ae8288a5c1e/Example/KWVerificationCodeView/Images.xcassets/AppIcon.appiconset/kw-logo-mark.png -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/ProgramaticalVerificationCodeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VerificationCodeViewController.swift 3 | // KWVerificationCodeView 4 | // 5 | // Created by KeepWorks on 01/10/2017. 6 | // Copyright (c) 2017 KeepWorks Technologies Pvt Ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import KWVerificationCodeView 11 | 12 | class ProgramaticalVerificationCodeViewController: UIViewController { 13 | 14 | // MARK: - IBOutlets 15 | @IBOutlet weak var containerView: UIView! 16 | 17 | // MARK: - Variables 18 | var verificationCodeView: KWVerificationCodeView? 19 | 20 | // MARK: - Lifecycle 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | 24 | verificationCodeView = KWVerificationCodeView(frame: CGRect(x: 0, y: 0, width: 240, height: 60)) 25 | containerView.addSubview(verificationCodeView!) 26 | } 27 | 28 | @IBAction func submitButtonTapped(_ sender: Any) { 29 | if verificationCodeView!.hasValidCode() { 30 | let alertController = UIAlertController(title: "Success", message: "Code is \(verificationCodeView!.getVerificationCode())", preferredStyle: .alert) 31 | let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil) 32 | alertController.addAction(okAction) 33 | present(alertController, animated: true, completion: nil) 34 | } 35 | } 36 | 37 | @IBAction func dismissButtonTapped(_ sender: Any) { 38 | dismiss(animated: true, completion: nil) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Example/KWVerificationCodeView/VerificationCodeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VerificationCodeViewController.swift 3 | // KWVerificationCodeView 4 | // 5 | // Created by KeepWorks on 01/10/2017. 6 | // Copyright (c) 2017 KeepWorks Technologies Pvt Ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import KWVerificationCodeView 11 | 12 | class VerificationCodeViewController: UIViewController { 13 | 14 | // MARK: - IBOutlets 15 | @IBOutlet weak var verificationCodeView: KWVerificationCodeView! 16 | @IBOutlet weak var submitButton: UIButton! 17 | 18 | // MARK: - Lifecycle 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | 22 | submitButton.isEnabled = false 23 | verificationCodeView.delegate = self 24 | 25 | /* Other available options 26 | verificationCodeView.keyboardType = UIKeyboardType.emailAddress 27 | verificationCodeView.set("1234") 28 | */ 29 | } 30 | 31 | // MARK: - IBAction 32 | @IBAction func submitButtonTapped(_ sender: UIButton) { 33 | if verificationCodeView.hasValidCode() { 34 | let alertController = UIAlertController(title: "Success", message: "Code is \(verificationCodeView.getVerificationCode())", preferredStyle: .alert) 35 | let okAction = UIAlertAction(title: "Ok", style: .default, handler: nil) 36 | alertController.addAction(okAction) 37 | present(alertController, animated: true, completion: nil) 38 | } 39 | } 40 | 41 | @IBAction func clearButtonTapped(_ sender: UIButton) { 42 | verificationCodeView.clear() 43 | } 44 | } 45 | 46 | // MARK: - KWVerificationCodeViewDelegate 47 | extension VerificationCodeViewController: KWVerificationCodeViewDelegate { 48 | func didChangeVerificationCode() { 49 | submitButton.isEnabled = verificationCodeView.hasValidCode() 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'KWVerificationCodeView_Example' do 4 | pod 'KWVerificationCodeView', :path => '../' 5 | 6 | target 'KWVerificationCodeView_Tests' do 7 | inherit! :search_paths 8 | end 9 | end 10 | 11 | post_install do |installer| 12 | installer.pods_project.targets.each do |target| 13 | target.build_configurations.each do |config| 14 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - KWVerificationCodeView (0.4.0) 3 | 4 | DEPENDENCIES: 5 | - KWVerificationCodeView (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | KWVerificationCodeView: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | KWVerificationCodeView: 92cca6ad028546d3232fa75cda3a40d00109a1a2 13 | 14 | PODFILE CHECKSUM: 38a262134d099738a8adda90500ebe0dd217c58a 15 | 16 | COCOAPODS: 1.12.1 17 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import XCTest 3 | import KWVerificationCodeView 4 | 5 | class Tests: XCTestCase { 6 | 7 | override func setUp() { 8 | super.setUp() 9 | // Put setup code here. This method is called before the invocation of each test method in the class. 10 | } 11 | 12 | override func tearDown() { 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | super.tearDown() 15 | } 16 | 17 | func testExample() { 18 | // This is an example of a functional test case. 19 | XCTAssert(true, "Pass") 20 | } 21 | 22 | func testPerformanceExample() { 23 | // This is an example of a performance test case. 24 | self.measure { 25 | // Put the code you want to measure the time of here. 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /KWVerificationCodeView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'KWVerificationCodeView' 3 | s.version = '0.5.0' 4 | s.summary = 'A verification code view with validation.' 5 | s.description = 'A customisable verification code view with built in validation. Can be used for one time passwords (OTPs), email verification codes etc.' 6 | s.homepage = 'https://github.com/keepworks/kwverificationcodeview' 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { 'KeepWorks' => 'ios@keepworks.com' } 9 | s.source = { :git => 'https://github.com/keepworks/kwverificationcodeview.git', :tag => s.version.to_s } 10 | 11 | s.ios.deployment_target = '12.0' 12 | s.source_files = 'KWVerificationCodeView/Classes/**/*' 13 | s.swift_version = '5.0' 14 | end 15 | -------------------------------------------------------------------------------- /KWVerificationCodeView/0.5.0/KWVerificationCodeView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'KWVerificationCodeView' 3 | s.version = '0.5.0' 4 | s.summary = 'A verification code view with validation.' 5 | s.description = 'A customisable verification code view with built in validation. Can be used for one time passwords (OTPs), email verification codes etc.' 6 | s.homepage = 'https://github.com/keepworks/kwverificationcodeview' 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { 'KeepWorks' => 'ios@keepworks.com' } 9 | s.source = { :git => 'https://github.com/keepworks/kwverificationcodeview.git', :tag => s.version.to_s } 10 | 11 | s.ios.deployment_target = '12.0' 12 | s.source_files = 'KWVerificationCodeView/Classes/**/*' 13 | s.swift_version = '5.0' 14 | end 15 | -------------------------------------------------------------------------------- /KWVerificationCodeView/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keepworks/KWVerificationCodeView/9556739aae59865e37e2d9981e680ae8288a5c1e/KWVerificationCodeView/Assets/.gitkeep -------------------------------------------------------------------------------- /KWVerificationCodeView/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keepworks/KWVerificationCodeView/9556739aae59865e37e2d9981e680ae8288a5c1e/KWVerificationCodeView/Classes/.gitkeep -------------------------------------------------------------------------------- /KWVerificationCodeView/Classes/Extensions/StringExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StringExtension.swift 3 | // Pods 4 | // 5 | // Created by KeepWorks on 5/27/16. 6 | // Copyright © 2017 KeepWorks Technologies Pvt Ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension String { 12 | func trim() -> String { 13 | return trimmingCharacters(in: CharacterSet.whitespaces) 14 | } 15 | 16 | func range(from nsRange: NSRange) -> Range? { 17 | guard 18 | let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex), 19 | let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex), 20 | let from = String.Index(from16, within: self), 21 | let to = String.Index(to16, within: self) 22 | else { return nil } 23 | return from ..< to 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /KWVerificationCodeView/Classes/Extensions/UIViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewExtension.swift 3 | // Pods 4 | // 5 | // Created by KeepWorks on 5/27/16. 6 | // Copyright © 2017 KeepWorks Technologies Pvt Ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | func loadViewFromNib() { 13 | let nibName = NSStringFromClass(type(of: self)).components(separatedBy: ".").last! 14 | let view = Bundle(for: type(of: self)).loadNibNamed(nibName, owner: self, options: nil)?.first as! UIView 15 | view.translatesAutoresizingMaskIntoConstraints = false 16 | addSubview(view) 17 | 18 | let views = ["view": view] 19 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: views)) 20 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: views)) 21 | setNeedsUpdateConstraints() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /KWVerificationCodeView/Classes/KWTextFieldView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KWTextFieldView.swift 3 | // Pods 4 | // 5 | // Created by KeepWorks on 13/01/17. 6 | // Copyright © 2017 KeepWorks Technologies Pvt Ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol KWTextFieldDelegate: AnyObject { 12 | func moveToNext(_ textFieldView: KWTextFieldView) 13 | func moveToPrevious(_ textFieldView: KWTextFieldView, oldCode: String) 14 | func didChangeCharacters() 15 | } 16 | 17 | @IBDesignable class KWTextFieldView: UIView { 18 | 19 | // MARK: - Constants 20 | static let maxCharactersLength = 1 21 | 22 | // MARK: - IBInspectables 23 | @IBInspectable var underlineColor: UIColor = UIColor.darkGray { 24 | didSet { 25 | underlineView.backgroundColor = underlineColor 26 | } 27 | } 28 | 29 | @IBInspectable var underlineSelectedColor: UIColor = UIColor.black 30 | 31 | @IBInspectable var textColor: UIColor = UIColor.darkText { 32 | didSet { 33 | numberTextField.textColor = textColor 34 | } 35 | } 36 | 37 | @IBInspectable var textSize: CGFloat = 24.0 { 38 | didSet { 39 | numberTextField.font = UIFont.systemFont(ofSize: textSize) 40 | } 41 | } 42 | 43 | @IBInspectable var textFont: String = "" { 44 | didSet { 45 | if let font = UIFont(name: textFont, size: textSize) { 46 | numberTextField.font = font 47 | } else { 48 | numberTextField.font = UIFont.systemFont(ofSize: textSize) 49 | } 50 | } 51 | } 52 | 53 | @IBInspectable var textFieldBackgroundColor: UIColor = UIColor.clear { 54 | didSet { 55 | numberTextField.backgroundColor = textFieldBackgroundColor 56 | } 57 | } 58 | 59 | @IBInspectable var textFieldTintColor: UIColor = UIColor.blue { 60 | didSet { 61 | numberTextField.tintColor = textFieldTintColor 62 | } 63 | } 64 | 65 | @IBInspectable var darkKeyboard: Bool = false { 66 | didSet { 67 | keyboardAppearance = darkKeyboard ? .dark : .light 68 | numberTextField.keyboardAppearance = keyboardAppearance 69 | } 70 | } 71 | 72 | // MARK: - IBOutlets 73 | @IBOutlet weak var numberTextField: UITextField! 74 | @IBOutlet weak private var underlineView: UIView! 75 | 76 | // MARK: - Variables 77 | private var keyboardAppearance = UIKeyboardAppearance.default 78 | weak var delegate: KWTextFieldDelegate? 79 | 80 | var code: String? { 81 | return numberTextField.text 82 | } 83 | 84 | // MARK: - Lifecycle 85 | override init(frame: CGRect) { 86 | super.init(frame: frame) 87 | 88 | setup() 89 | } 90 | 91 | required public init?(coder aDecoder: NSCoder) { 92 | super.init(coder: aDecoder) 93 | 94 | setup() 95 | } 96 | 97 | deinit { 98 | NotificationCenter.default.removeObserver(self) 99 | } 100 | 101 | // MARK: - Public Methods 102 | public func activate() { 103 | numberTextField.becomeFirstResponder() 104 | if numberTextField.text?.count == 0 { 105 | numberTextField.text = " " 106 | } 107 | } 108 | 109 | public func deactivate() { 110 | numberTextField.resignFirstResponder() 111 | } 112 | 113 | public func reset() { 114 | numberTextField.text = " " 115 | updateUnderline() 116 | } 117 | 118 | // MARK: - Private Methods 119 | private func setup() { 120 | loadViewFromNib() 121 | numberTextField.delegate = self 122 | numberTextField.autocorrectionType = UITextAutocorrectionType.no 123 | 124 | NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChange(_:)), name: UITextField.textDidChangeNotification, object: numberTextField) 125 | } 126 | 127 | private func updateUnderline() { 128 | underlineView.backgroundColor = numberTextField.text?.trim() != "" ? underlineSelectedColor : underlineColor 129 | } 130 | 131 | @objc private func textFieldDidChange(_ notification: Foundation.Notification) { 132 | if numberTextField.text?.count == 0 { 133 | numberTextField.text = " " 134 | } 135 | } 136 | } 137 | 138 | // MARK: - UITextFieldDelegate 139 | extension KWTextFieldView: UITextFieldDelegate { 140 | public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { 141 | let currentString = numberTextField.text! 142 | let newString = currentString.replacingCharacters(in: textField.text!.range(from: range)!, with: string) 143 | 144 | if newString.count > type(of: self).maxCharactersLength { 145 | delegate?.moveToNext(self) 146 | textField.text = string 147 | } else if newString.count == 0 { 148 | delegate?.moveToPrevious(self, oldCode: textField.text!) 149 | numberTextField.text = " " 150 | } 151 | 152 | delegate?.didChangeCharacters() 153 | updateUnderline() 154 | 155 | return newString.count <= type(of: self).maxCharactersLength 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /KWVerificationCodeView/Classes/KWTextFieldView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /KWVerificationCodeView/Classes/KWVerificationCodeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KWVerificationCodeView.swift 3 | // Pods 4 | // 5 | // Created by KeepWorks on 11/01/17. 6 | // Copyright © 2017 KeepWorks Technologies Pvt Ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol KWVerificationCodeViewDelegate: AnyObject { 12 | func didChangeVerificationCode() 13 | } 14 | 15 | @IBDesignable open class KWVerificationCodeView: UIView { 16 | 17 | // MARK: - Constants 18 | private let minDigits: UInt8 = 2 19 | private let maxDigits: UInt8 = 8 20 | private let textFieldViewLeadingSpace: CGFloat = 10 21 | private let textFieldViewVerticalSpace: CGFloat = 6 22 | 23 | // MARK: - IBInspectables 24 | @IBInspectable public var underlineColor: UIColor = UIColor.darkGray { 25 | didSet { 26 | for textFieldView in textFieldViews { 27 | textFieldView.underlineColor = underlineColor 28 | } 29 | } 30 | } 31 | 32 | @IBInspectable public var underlineSelectedColor: UIColor = UIColor.black { 33 | didSet { 34 | for textFieldView in textFieldViews { 35 | textFieldView.underlineSelectedColor = underlineSelectedColor 36 | } 37 | } 38 | } 39 | 40 | @IBInspectable public var textColor: UIColor = UIColor.darkText { 41 | didSet { 42 | for textFieldView in textFieldViews { 43 | textFieldView.numberTextField.textColor = textColor 44 | } 45 | } 46 | } 47 | 48 | @IBInspectable public var digits: UInt8 = 4 { 49 | didSet { 50 | setupTextFieldViews() 51 | } 52 | } 53 | 54 | @IBInspectable public var textSize: CGFloat = 24.0 { 55 | didSet { 56 | for textFieldView in textFieldViews { 57 | textFieldView.numberTextField.font = UIFont.systemFont(ofSize: textSize) 58 | } 59 | } 60 | } 61 | 62 | @IBInspectable public var textFont: String = "" { 63 | didSet { 64 | if let font = UIFont(name: textFont.trim(), size: textSize) { 65 | textFieldFont = font 66 | } else { 67 | textFieldFont = UIFont.systemFont(ofSize: textSize) 68 | } 69 | 70 | for textFieldView in textFieldViews { 71 | textFieldView.numberTextField.font = textFieldFont 72 | } 73 | } 74 | } 75 | 76 | @IBInspectable public var textFieldBackgroundColor: UIColor = UIColor.clear { 77 | didSet { 78 | for textFieldView in textFieldViews { 79 | textFieldView.numberTextField.backgroundColor = textFieldBackgroundColor 80 | } 81 | } 82 | } 83 | 84 | @IBInspectable public var textFieldTintColor: UIColor = UIColor.blue { 85 | didSet { 86 | for textFieldView in textFieldViews { 87 | textFieldView.numberTextField.tintColor = textFieldTintColor 88 | } 89 | } 90 | } 91 | 92 | @IBInspectable public var darkKeyboard: Bool = false { 93 | didSet { 94 | keyboardAppearance = darkKeyboard ? .dark : .light 95 | for textFieldView in textFieldViews { 96 | textFieldView.numberTextField.keyboardAppearance = keyboardAppearance 97 | } 98 | } 99 | } 100 | 101 | public var keyboardType: UIKeyboardType = UIKeyboardType.numberPad { 102 | didSet { 103 | for textFieldView in textFieldViews { 104 | textFieldView.numberTextField.keyboardType = keyboardType 105 | } 106 | } 107 | } 108 | 109 | public var textContentType: UITextContentType = UITextContentType.oneTimeCode { 110 | didSet { 111 | for textFieldView in textFieldViews { 112 | textFieldView.numberTextField.textContentType = textContentType 113 | } 114 | } 115 | } 116 | 117 | // MARK: - IBOutlets 118 | @IBOutlet var view: UIView! 119 | 120 | // MARK: - Variables 121 | public var isTappable: Bool = false { 122 | didSet { 123 | view.isUserInteractionEnabled = isTappable 124 | } 125 | } 126 | 127 | private var textFieldViews = [KWTextFieldView]() 128 | private var keyboardAppearance = UIKeyboardAppearance.default 129 | private var textFieldFont = UIFont.systemFont(ofSize: 24.0) 130 | private var requiredDigits: UInt8 { 131 | switch digits { 132 | case minDigits...maxDigits: 133 | return digits 134 | 135 | case 0.. String { 164 | var verificationCode = "" 165 | for textFieldView in textFieldViews { 166 | verificationCode += textFieldView.numberTextField.text! 167 | } 168 | 169 | return verificationCode 170 | } 171 | 172 | public func set(_ code: String) { 173 | guard code.count == textFieldViews.count else { 174 | print("Code length doesn't match the textFields length.") 175 | return 176 | } 177 | 178 | for (index, char) in code.enumerated() { 179 | let textfield = textFieldViews[index] 180 | textfield.numberTextField.text = String(char) 181 | } 182 | 183 | delegate?.didChangeVerificationCode() 184 | } 185 | 186 | public func hasValidCode() -> Bool { 187 | for textFieldView in textFieldViews { 188 | if textFieldView.numberTextField.text!.trim() == "" { 189 | return false 190 | } 191 | } 192 | 193 | return true 194 | } 195 | 196 | public func clear() { 197 | for textFieldView in textFieldViews { 198 | textFieldView.numberTextField.text = "" 199 | } 200 | 201 | textFieldViews[0].activate() 202 | delegate?.didChangeVerificationCode() 203 | } 204 | 205 | // MARK: - Private Methods 206 | private func setup() { 207 | loadViewFromNib() 208 | 209 | setupTextFieldViews() 210 | setupVerificationCodeView() 211 | } 212 | 213 | private func setupTextFieldViews() { 214 | textFieldViews.forEach { $0.removeFromSuperview() } 215 | textFieldViews.removeAll() 216 | 217 | let textFieldViewWidth = (frame.size.width - (textFieldViewLeadingSpace * (CGFloat(requiredDigits) + 1))) / CGFloat(requiredDigits) 218 | let textFieldViewHeight: CGFloat = frame.size.height - (textFieldViewVerticalSpace * 2) 219 | var currentX = textFieldViewLeadingSpace 220 | for _ in 0.. 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 KeepWorks Technologies Pvt Ltd 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KWVerificationCodeView 2 | 3 | [![Build Status](https://app.bitrise.io/app/df05a5313a9741ef/status.svg?token=NNC-GCKiEh6G4w7MJ6bM5Q&branch=master)](https://app.bitrise.io/app/df05a5313a9741ef) 4 | [![Version](https://img.shields.io/cocoapods/v/KWVerificationCodeView.svg?style=flat)](http://cocoapods.org/pods/KWVerificationCodeView) 5 | [![License](https://img.shields.io/cocoapods/l/KWVerificationCodeView.svg?style=flat)](http://cocoapods.org/pods/KWVerificationCodeView) 6 | [![Platform](https://img.shields.io/cocoapods/p/KWVerificationCodeView.svg?style=flat)](http://cocoapods.org/pods/KWVerificationCodeView) 7 | 8 | A customisable verification code view with built in validation. Can be used for one time passwords (OTPs), email verification codes etc. 9 | 10 | ![Screenshot](Screenshots/KWVerificationCodeView.gif) 11 | 12 | ## Example 13 | 14 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 15 | 16 | ## Requirements 17 | - iOS 12 or later 18 | - Swift 5.0 19 | - Latest Xcode 20 | 21 | ## Installation 22 | 23 | KWVerificationCodeView is available through [CocoaPods](http://cocoapods.org). To install 24 | it, simply add the following line to your Podfile: 25 | 26 | ```ruby 27 | pod "KWVerificationCodeView" 28 | ``` 29 | 30 | Or for `Swift 4.2` support use 31 | ```ruby 32 | pod "KWVerificationCodeView", '0.3.0' 33 | ``` 34 | 35 | Or for `Swift 4` use: 36 | ```ruby 37 | pod "KWVerificationCodeView", '0.2.0' 38 | ``` 39 | 40 | 41 | ## Usage 42 | 43 | Add a `UIView` in your *Storyboard* and change the class to `KWVerificationCodeView`. You can set the properties in the *Attributes Inspector* and see a live preview: 44 | 45 | ![Interface Builder Screenshot](Screenshots/interfacebuilder.png) 46 | 47 | The properties which can be directly set in the *Attributes Inspector* and their default values are as follows: 48 | 49 | - `Underline Color` - Dark Gray Color 50 | 51 | - `Underline Selected Color` - Black Color 52 | 53 | - `Text Color` - Dark Text Color 54 | 55 | - `Digits` - 4 56 | 57 | - `Text Size` - 24.0 58 | 59 | - `Text Font` - System Font 60 | 61 | - `Text Field Background Color` - Clear Color 62 | 63 | - `Text Field Tint Color` - Blue Color 64 | 65 | - `Dark Keyboard` - Default Keyboard Appearance 66 | 67 | Customizable properties 68 | 69 | - `keyboardType` - Sets the keyboard type (Defaults to Number Pad when not set) 70 | 71 | verificationCodeView.keyboardType = UIKeyboardType.emailAddress 72 | 73 | 74 | ### Variables 75 | 76 | The `KWVerificationCodeView` has the following variables: 77 | 78 | isTappable: Bool 79 | 80 | Makes the KWVerficationCodeView tappable. Default value is `false` 81 | 82 | ### Methods 83 | 84 | The `KWVerificationCodeView` has the following methods: 85 | 86 | hasValidCode() -> Bool 87 | 88 | Returns true when the entered code is valid. 89 | 90 | getVerificationCode() -> String 91 | 92 | Returns the validation code. 93 | 94 | set(code: String) 95 | 96 | Set verification code programatically by passing code as a string 97 | 98 | focus() 99 | 100 | Focus on First Text Field 101 | 102 | clear() 103 | 104 | Clears the verification code view and first field becomes first responder 105 | 106 | ### Protocols 107 | 108 | #### KWVerificationCodeViewDelegate 109 | 110 | KWVerificationCodeViewDelegate protocol has the following method: 111 | 112 | didChangeVerificationCode() 113 | 114 | Notifies that the text in `KWVerificationCodeView` has been changed. This is especially useful in situations where you have to enable the submit button only if the verification code is valid. 115 | 116 | ## Author 117 | 118 | KeepWorks, ios@keepworks.com 119 | 120 | ## Credits 121 | 122 | KWVerificationCodeView is owned and maintained by [KeepWorks](http://www.keepworks.com/). 123 | 124 | [![N|Solid](./logo.png)](http://www.keepworks.com/) 125 | 126 | ## Contributing 127 | 128 | Bug reports and pull requests are welcome on GitHub at https://github.com/keepworks/KWVerificationCodeView. 129 | 130 | ## License 131 | 132 | KWVerificationCodeView is available under the [MIT License](http://opensource.org/licenses/MIT). See the [License](https://github.com/keepworks/KWVerificationCodeView/blob/master/LICENSE) file for more info. 133 | -------------------------------------------------------------------------------- /Screenshots/KWVerificationCodeView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keepworks/KWVerificationCodeView/9556739aae59865e37e2d9981e680ae8288a5c1e/Screenshots/KWVerificationCodeView.gif -------------------------------------------------------------------------------- /Screenshots/interfacebuilder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keepworks/KWVerificationCodeView/9556739aae59865e37e2d9981e680ae8288a5c1e/Screenshots/interfacebuilder.png -------------------------------------------------------------------------------- /Screenshots/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keepworks/KWVerificationCodeView/9556739aae59865e37e2d9981e680ae8288a5c1e/Screenshots/screenshot.png -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keepworks/KWVerificationCodeView/9556739aae59865e37e2d9981e680ae8288a5c1e/logo.png --------------------------------------------------------------------------------