├── .gitignore ├── Passcode.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── cruzdiary.xcuserdatad │ └── xcschemes │ ├── Passcode.xcscheme │ └── xcschememanagement.plist ├── Passcode.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── Passcode ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── KeyCell.swift ├── KeyCell.xib ├── KeySectionController.swift ├── PasscodeViewController.swift ├── PasscodeViewReactor.swift └── RxIGListAdapterDataSource.swift ├── PasscodeTests ├── Info.plist └── PasscodeTests.swift ├── Podfile ├── Podfile.lock └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | Carthage/Checkouts 54 | 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | -------------------------------------------------------------------------------- /Passcode.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1BD93BD99E6368531593039C /* Pods_Passcode_PasscodeTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D9BE90CF98A49131D3DB79C /* Pods_Passcode_PasscodeTests.framework */; }; 11 | 4C3CD4C71ED09A4F00B3FBD7 /* RxIGListAdapterDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C3CD4C61ED09A4F00B3FBD7 /* RxIGListAdapterDataSource.swift */; }; 12 | 4C4BF1B41ED02B2800AD7044 /* KeyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4BF1B21ED02B2800AD7044 /* KeyCell.swift */; }; 13 | 4C4BF1B51ED02B2800AD7044 /* KeyCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C4BF1B31ED02B2800AD7044 /* KeyCell.xib */; }; 14 | 4C4BF1B71ED02B9B00AD7044 /* KeySectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4BF1B61ED02B9B00AD7044 /* KeySectionController.swift */; }; 15 | 4CBCC0F11ECDE78800B8522C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBCC0F01ECDE78800B8522C /* AppDelegate.swift */; }; 16 | 4CBCC0F31ECDE78800B8522C /* PasscodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBCC0F21ECDE78800B8522C /* PasscodeViewController.swift */; }; 17 | 4CBCC0F61ECDE78800B8522C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4CBCC0F41ECDE78800B8522C /* Main.storyboard */; }; 18 | 4CBCC0F81ECDE78800B8522C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4CBCC0F71ECDE78800B8522C /* Assets.xcassets */; }; 19 | 4CBCC0FB1ECDE78800B8522C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4CBCC0F91ECDE78800B8522C /* LaunchScreen.storyboard */; }; 20 | 4CBCC1061ECDE78800B8522C /* PasscodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBCC1051ECDE78800B8522C /* PasscodeTests.swift */; }; 21 | 4CBCC1111ECDF01E00B8522C /* PasscodeViewReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CBCC1101ECDF01E00B8522C /* PasscodeViewReactor.swift */; }; 22 | 5097F8CAD89A73E9429BC903 /* Pods_Passcode.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 56FAA6B77DA433879519B306 /* Pods_Passcode.framework */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 4CBCC1021ECDE78800B8522C /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 4CBCC0E51ECDE78800B8522C /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 4CBCC0EC1ECDE78800B8522C; 31 | remoteInfo = Passcode; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXFileReference section */ 36 | 0C5FC3B273A2F8B5A25D54C6 /* Pods-Passcode-PasscodeTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passcode-PasscodeTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Passcode-PasscodeTests/Pods-Passcode-PasscodeTests.release.xcconfig"; sourceTree = ""; }; 37 | 3D9BE90CF98A49131D3DB79C /* Pods_Passcode_PasscodeTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Passcode_PasscodeTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 4C3CD4C61ED09A4F00B3FBD7 /* RxIGListAdapterDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxIGListAdapterDataSource.swift; sourceTree = ""; }; 39 | 4C4BF1B21ED02B2800AD7044 /* KeyCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyCell.swift; sourceTree = ""; }; 40 | 4C4BF1B31ED02B2800AD7044 /* KeyCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KeyCell.xib; sourceTree = ""; }; 41 | 4C4BF1B61ED02B9B00AD7044 /* KeySectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeySectionController.swift; sourceTree = ""; }; 42 | 4CBCC0ED1ECDE78800B8522C /* Passcode.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Passcode.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 4CBCC0F01ECDE78800B8522C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 44 | 4CBCC0F21ECDE78800B8522C /* PasscodeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasscodeViewController.swift; sourceTree = ""; }; 45 | 4CBCC0F51ECDE78800B8522C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 46 | 4CBCC0F71ECDE78800B8522C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 47 | 4CBCC0FA1ECDE78800B8522C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 48 | 4CBCC0FC1ECDE78800B8522C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 4CBCC1011ECDE78800B8522C /* PasscodeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PasscodeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 4CBCC1051ECDE78800B8522C /* PasscodeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasscodeTests.swift; sourceTree = ""; }; 51 | 4CBCC1071ECDE78800B8522C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 4CBCC1101ECDF01E00B8522C /* PasscodeViewReactor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeViewReactor.swift; sourceTree = ""; }; 53 | 56FAA6B77DA433879519B306 /* Pods_Passcode.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Passcode.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | A9DA607C5C71663F7F3416DD /* Pods-Passcode.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passcode.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Passcode/Pods-Passcode.debug.xcconfig"; sourceTree = ""; }; 55 | BB1E9C33C6F9122D62082B3D /* Pods-Passcode.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passcode.release.xcconfig"; path = "Pods/Target Support Files/Pods-Passcode/Pods-Passcode.release.xcconfig"; sourceTree = ""; }; 56 | E8FA8563A6C27970CFE7F06F /* Pods-Passcode-PasscodeTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Passcode-PasscodeTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Passcode-PasscodeTests/Pods-Passcode-PasscodeTests.debug.xcconfig"; sourceTree = ""; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | 4CBCC0EA1ECDE78800B8522C /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | 5097F8CAD89A73E9429BC903 /* Pods_Passcode.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | 4CBCC0FE1ECDE78800B8522C /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | 1BD93BD99E6368531593039C /* Pods_Passcode_PasscodeTests.framework in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 214B5CB35B21A476125034F0 /* Frameworks */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 56FAA6B77DA433879519B306 /* Pods_Passcode.framework */, 83 | 3D9BE90CF98A49131D3DB79C /* Pods_Passcode_PasscodeTests.framework */, 84 | ); 85 | name = Frameworks; 86 | sourceTree = ""; 87 | }; 88 | 4CBCC0E41ECDE78800B8522C = { 89 | isa = PBXGroup; 90 | children = ( 91 | 4CBCC0EF1ECDE78800B8522C /* Passcode */, 92 | 4CBCC1041ECDE78800B8522C /* PasscodeTests */, 93 | 4CBCC0EE1ECDE78800B8522C /* Products */, 94 | AFA3B798769A4ECC1389C30C /* Pods */, 95 | 214B5CB35B21A476125034F0 /* Frameworks */, 96 | ); 97 | sourceTree = ""; 98 | }; 99 | 4CBCC0EE1ECDE78800B8522C /* Products */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 4CBCC0ED1ECDE78800B8522C /* Passcode.app */, 103 | 4CBCC1011ECDE78800B8522C /* PasscodeTests.xctest */, 104 | ); 105 | name = Products; 106 | sourceTree = ""; 107 | }; 108 | 4CBCC0EF1ECDE78800B8522C /* Passcode */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 4CBCC0F01ECDE78800B8522C /* AppDelegate.swift */, 112 | 4C4BF1B21ED02B2800AD7044 /* KeyCell.swift */, 113 | 4C4BF1B31ED02B2800AD7044 /* KeyCell.xib */, 114 | 4C4BF1B61ED02B9B00AD7044 /* KeySectionController.swift */, 115 | 4CBCC0F21ECDE78800B8522C /* PasscodeViewController.swift */, 116 | 4CBCC1101ECDF01E00B8522C /* PasscodeViewReactor.swift */, 117 | 4C3CD4C61ED09A4F00B3FBD7 /* RxIGListAdapterDataSource.swift */, 118 | 4CBCC0F41ECDE78800B8522C /* Main.storyboard */, 119 | 4CBCC0F71ECDE78800B8522C /* Assets.xcassets */, 120 | 4CBCC0F91ECDE78800B8522C /* LaunchScreen.storyboard */, 121 | 4CBCC0FC1ECDE78800B8522C /* Info.plist */, 122 | ); 123 | path = Passcode; 124 | sourceTree = ""; 125 | }; 126 | 4CBCC1041ECDE78800B8522C /* PasscodeTests */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 4CBCC1051ECDE78800B8522C /* PasscodeTests.swift */, 130 | 4CBCC1071ECDE78800B8522C /* Info.plist */, 131 | ); 132 | path = PasscodeTests; 133 | sourceTree = ""; 134 | }; 135 | AFA3B798769A4ECC1389C30C /* Pods */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | A9DA607C5C71663F7F3416DD /* Pods-Passcode.debug.xcconfig */, 139 | BB1E9C33C6F9122D62082B3D /* Pods-Passcode.release.xcconfig */, 140 | E8FA8563A6C27970CFE7F06F /* Pods-Passcode-PasscodeTests.debug.xcconfig */, 141 | 0C5FC3B273A2F8B5A25D54C6 /* Pods-Passcode-PasscodeTests.release.xcconfig */, 142 | ); 143 | name = Pods; 144 | sourceTree = ""; 145 | }; 146 | /* End PBXGroup section */ 147 | 148 | /* Begin PBXNativeTarget section */ 149 | 4CBCC0EC1ECDE78800B8522C /* Passcode */ = { 150 | isa = PBXNativeTarget; 151 | buildConfigurationList = 4CBCC10A1ECDE78800B8522C /* Build configuration list for PBXNativeTarget "Passcode" */; 152 | buildPhases = ( 153 | 8353567895A7C2160D4DB062 /* [CP] Check Pods Manifest.lock */, 154 | 4CBCC0E91ECDE78800B8522C /* Sources */, 155 | 4CBCC0EA1ECDE78800B8522C /* Frameworks */, 156 | 4CBCC0EB1ECDE78800B8522C /* Resources */, 157 | 0499F5D53A05D5E6CAC55D9A /* [CP] Embed Pods Frameworks */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | ); 163 | name = Passcode; 164 | productName = Passcode; 165 | productReference = 4CBCC0ED1ECDE78800B8522C /* Passcode.app */; 166 | productType = "com.apple.product-type.application"; 167 | }; 168 | 4CBCC1001ECDE78800B8522C /* PasscodeTests */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = 4CBCC10D1ECDE78800B8522C /* Build configuration list for PBXNativeTarget "PasscodeTests" */; 171 | buildPhases = ( 172 | 8AD260E3BCB2F20409588FAE /* [CP] Check Pods Manifest.lock */, 173 | 4CBCC0FD1ECDE78800B8522C /* Sources */, 174 | 4CBCC0FE1ECDE78800B8522C /* Frameworks */, 175 | 4CBCC0FF1ECDE78800B8522C /* Resources */, 176 | B1A00FD390142CC5E41A9C6A /* [CP] Embed Pods Frameworks */, 177 | ); 178 | buildRules = ( 179 | ); 180 | dependencies = ( 181 | 4CBCC1031ECDE78800B8522C /* PBXTargetDependency */, 182 | ); 183 | name = PasscodeTests; 184 | productName = PasscodeTests; 185 | productReference = 4CBCC1011ECDE78800B8522C /* PasscodeTests.xctest */; 186 | productType = "com.apple.product-type.bundle.unit-test"; 187 | }; 188 | /* End PBXNativeTarget section */ 189 | 190 | /* Begin PBXProject section */ 191 | 4CBCC0E51ECDE78800B8522C /* Project object */ = { 192 | isa = PBXProject; 193 | attributes = { 194 | LastSwiftUpdateCheck = 0830; 195 | LastUpgradeCheck = 1000; 196 | ORGANIZATIONNAME = Cruz; 197 | TargetAttributes = { 198 | 4CBCC0EC1ECDE78800B8522C = { 199 | CreatedOnToolsVersion = 8.3.2; 200 | DevelopmentTeam = 3YN6YPP3YC; 201 | ProvisioningStyle = Automatic; 202 | }; 203 | 4CBCC1001ECDE78800B8522C = { 204 | CreatedOnToolsVersion = 8.3.2; 205 | DevelopmentTeam = 3YN6YPP3YC; 206 | ProvisioningStyle = Automatic; 207 | TestTargetID = 4CBCC0EC1ECDE78800B8522C; 208 | }; 209 | }; 210 | }; 211 | buildConfigurationList = 4CBCC0E81ECDE78800B8522C /* Build configuration list for PBXProject "Passcode" */; 212 | compatibilityVersion = "Xcode 3.2"; 213 | developmentRegion = English; 214 | hasScannedForEncodings = 0; 215 | knownRegions = ( 216 | en, 217 | Base, 218 | ); 219 | mainGroup = 4CBCC0E41ECDE78800B8522C; 220 | productRefGroup = 4CBCC0EE1ECDE78800B8522C /* Products */; 221 | projectDirPath = ""; 222 | projectRoot = ""; 223 | targets = ( 224 | 4CBCC0EC1ECDE78800B8522C /* Passcode */, 225 | 4CBCC1001ECDE78800B8522C /* PasscodeTests */, 226 | ); 227 | }; 228 | /* End PBXProject section */ 229 | 230 | /* Begin PBXResourcesBuildPhase section */ 231 | 4CBCC0EB1ECDE78800B8522C /* Resources */ = { 232 | isa = PBXResourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 4CBCC0FB1ECDE78800B8522C /* LaunchScreen.storyboard in Resources */, 236 | 4CBCC0F81ECDE78800B8522C /* Assets.xcassets in Resources */, 237 | 4CBCC0F61ECDE78800B8522C /* Main.storyboard in Resources */, 238 | 4C4BF1B51ED02B2800AD7044 /* KeyCell.xib in Resources */, 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | }; 242 | 4CBCC0FF1ECDE78800B8522C /* Resources */ = { 243 | isa = PBXResourcesBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | }; 249 | /* End PBXResourcesBuildPhase section */ 250 | 251 | /* Begin PBXShellScriptBuildPhase section */ 252 | 0499F5D53A05D5E6CAC55D9A /* [CP] Embed Pods Frameworks */ = { 253 | isa = PBXShellScriptBuildPhase; 254 | buildActionMask = 2147483647; 255 | files = ( 256 | ); 257 | inputPaths = ( 258 | "${PODS_ROOT}/Target Support Files/Pods-Passcode/Pods-Passcode-frameworks.sh", 259 | "${BUILT_PRODUCTS_DIR}/Device/Device.framework", 260 | "${BUILT_PRODUCTS_DIR}/DeviceLayout/DeviceLayout.framework", 261 | "${BUILT_PRODUCTS_DIR}/GSMessages/GSMessages.framework", 262 | "${BUILT_PRODUCTS_DIR}/IGListKit/IGListKit.framework", 263 | "${BUILT_PRODUCTS_DIR}/Pastel/Pastel.framework", 264 | "${BUILT_PRODUCTS_DIR}/ReactorKit/ReactorKit.framework", 265 | "${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework", 266 | "${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework", 267 | ); 268 | name = "[CP] Embed Pods Frameworks"; 269 | outputPaths = ( 270 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Device.framework", 271 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceLayout.framework", 272 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GSMessages.framework", 273 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IGListKit.framework", 274 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Pastel.framework", 275 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactorKit.framework", 276 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework", 277 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework", 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | shellPath = /bin/sh; 281 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Passcode/Pods-Passcode-frameworks.sh\"\n"; 282 | showEnvVarsInLog = 0; 283 | }; 284 | 8353567895A7C2160D4DB062 /* [CP] Check Pods Manifest.lock */ = { 285 | isa = PBXShellScriptBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | ); 289 | inputPaths = ( 290 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 291 | "${PODS_ROOT}/Manifest.lock", 292 | ); 293 | name = "[CP] Check Pods Manifest.lock"; 294 | outputPaths = ( 295 | "$(DERIVED_FILE_DIR)/Pods-Passcode-checkManifestLockResult.txt", 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | shellPath = /bin/sh; 299 | 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"; 300 | showEnvVarsInLog = 0; 301 | }; 302 | 8AD260E3BCB2F20409588FAE /* [CP] Check Pods Manifest.lock */ = { 303 | isa = PBXShellScriptBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | ); 307 | inputPaths = ( 308 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 309 | "${PODS_ROOT}/Manifest.lock", 310 | ); 311 | name = "[CP] Check Pods Manifest.lock"; 312 | outputPaths = ( 313 | "$(DERIVED_FILE_DIR)/Pods-Passcode-PasscodeTests-checkManifestLockResult.txt", 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | shellPath = /bin/sh; 317 | 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"; 318 | showEnvVarsInLog = 0; 319 | }; 320 | B1A00FD390142CC5E41A9C6A /* [CP] Embed Pods Frameworks */ = { 321 | isa = PBXShellScriptBuildPhase; 322 | buildActionMask = 2147483647; 323 | files = ( 324 | ); 325 | inputPaths = ( 326 | "${PODS_ROOT}/Target Support Files/Pods-Passcode-PasscodeTests/Pods-Passcode-PasscodeTests-frameworks.sh", 327 | "${BUILT_PRODUCTS_DIR}/Device/Device.framework", 328 | "${BUILT_PRODUCTS_DIR}/DeviceLayout/DeviceLayout.framework", 329 | "${BUILT_PRODUCTS_DIR}/GSMessages/GSMessages.framework", 330 | "${BUILT_PRODUCTS_DIR}/IGListKit/IGListKit.framework", 331 | "${BUILT_PRODUCTS_DIR}/Pastel/Pastel.framework", 332 | "${BUILT_PRODUCTS_DIR}/ReactorKit/ReactorKit.framework", 333 | "${BUILT_PRODUCTS_DIR}/RxCocoa/RxCocoa.framework", 334 | "${BUILT_PRODUCTS_DIR}/RxSwift/RxSwift.framework", 335 | "${BUILT_PRODUCTS_DIR}/RxExpect/RxExpect.framework", 336 | "${BUILT_PRODUCTS_DIR}/RxTest/RxTest.framework", 337 | ); 338 | name = "[CP] Embed Pods Frameworks"; 339 | outputPaths = ( 340 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Device.framework", 341 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DeviceLayout.framework", 342 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GSMessages.framework", 343 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IGListKit.framework", 344 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Pastel.framework", 345 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactorKit.framework", 346 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxCocoa.framework", 347 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxSwift.framework", 348 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxExpect.framework", 349 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxTest.framework", 350 | ); 351 | runOnlyForDeploymentPostprocessing = 0; 352 | shellPath = /bin/sh; 353 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Passcode-PasscodeTests/Pods-Passcode-PasscodeTests-frameworks.sh\"\n"; 354 | showEnvVarsInLog = 0; 355 | }; 356 | /* End PBXShellScriptBuildPhase section */ 357 | 358 | /* Begin PBXSourcesBuildPhase section */ 359 | 4CBCC0E91ECDE78800B8522C /* Sources */ = { 360 | isa = PBXSourcesBuildPhase; 361 | buildActionMask = 2147483647; 362 | files = ( 363 | 4CBCC1111ECDF01E00B8522C /* PasscodeViewReactor.swift in Sources */, 364 | 4CBCC0F31ECDE78800B8522C /* PasscodeViewController.swift in Sources */, 365 | 4CBCC0F11ECDE78800B8522C /* AppDelegate.swift in Sources */, 366 | 4C4BF1B71ED02B9B00AD7044 /* KeySectionController.swift in Sources */, 367 | 4C3CD4C71ED09A4F00B3FBD7 /* RxIGListAdapterDataSource.swift in Sources */, 368 | 4C4BF1B41ED02B2800AD7044 /* KeyCell.swift in Sources */, 369 | ); 370 | runOnlyForDeploymentPostprocessing = 0; 371 | }; 372 | 4CBCC0FD1ECDE78800B8522C /* Sources */ = { 373 | isa = PBXSourcesBuildPhase; 374 | buildActionMask = 2147483647; 375 | files = ( 376 | 4CBCC1061ECDE78800B8522C /* PasscodeTests.swift in Sources */, 377 | ); 378 | runOnlyForDeploymentPostprocessing = 0; 379 | }; 380 | /* End PBXSourcesBuildPhase section */ 381 | 382 | /* Begin PBXTargetDependency section */ 383 | 4CBCC1031ECDE78800B8522C /* PBXTargetDependency */ = { 384 | isa = PBXTargetDependency; 385 | target = 4CBCC0EC1ECDE78800B8522C /* Passcode */; 386 | targetProxy = 4CBCC1021ECDE78800B8522C /* PBXContainerItemProxy */; 387 | }; 388 | /* End PBXTargetDependency section */ 389 | 390 | /* Begin PBXVariantGroup section */ 391 | 4CBCC0F41ECDE78800B8522C /* Main.storyboard */ = { 392 | isa = PBXVariantGroup; 393 | children = ( 394 | 4CBCC0F51ECDE78800B8522C /* Base */, 395 | ); 396 | name = Main.storyboard; 397 | sourceTree = ""; 398 | }; 399 | 4CBCC0F91ECDE78800B8522C /* LaunchScreen.storyboard */ = { 400 | isa = PBXVariantGroup; 401 | children = ( 402 | 4CBCC0FA1ECDE78800B8522C /* Base */, 403 | ); 404 | name = LaunchScreen.storyboard; 405 | sourceTree = ""; 406 | }; 407 | /* End PBXVariantGroup section */ 408 | 409 | /* Begin XCBuildConfiguration section */ 410 | 4CBCC1081ECDE78800B8522C /* Debug */ = { 411 | isa = XCBuildConfiguration; 412 | buildSettings = { 413 | ALWAYS_SEARCH_USER_PATHS = NO; 414 | CLANG_ANALYZER_NONNULL = YES; 415 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 416 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 417 | CLANG_CXX_LIBRARY = "libc++"; 418 | CLANG_ENABLE_MODULES = YES; 419 | CLANG_ENABLE_OBJC_ARC = YES; 420 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 421 | CLANG_WARN_BOOL_CONVERSION = YES; 422 | CLANG_WARN_COMMA = YES; 423 | CLANG_WARN_CONSTANT_CONVERSION = YES; 424 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 425 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 426 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 427 | CLANG_WARN_EMPTY_BODY = YES; 428 | CLANG_WARN_ENUM_CONVERSION = YES; 429 | CLANG_WARN_INFINITE_RECURSION = YES; 430 | CLANG_WARN_INT_CONVERSION = YES; 431 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 432 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 433 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 434 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 435 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 436 | CLANG_WARN_STRICT_PROTOTYPES = YES; 437 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 438 | CLANG_WARN_UNREACHABLE_CODE = YES; 439 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 440 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 441 | COPY_PHASE_STRIP = NO; 442 | DEBUG_INFORMATION_FORMAT = dwarf; 443 | ENABLE_STRICT_OBJC_MSGSEND = YES; 444 | ENABLE_TESTABILITY = YES; 445 | GCC_C_LANGUAGE_STANDARD = gnu99; 446 | GCC_DYNAMIC_NO_PIC = NO; 447 | GCC_NO_COMMON_BLOCKS = YES; 448 | GCC_OPTIMIZATION_LEVEL = 0; 449 | GCC_PREPROCESSOR_DEFINITIONS = ( 450 | "DEBUG=1", 451 | "$(inherited)", 452 | ); 453 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 454 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 455 | GCC_WARN_UNDECLARED_SELECTOR = YES; 456 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 457 | GCC_WARN_UNUSED_FUNCTION = YES; 458 | GCC_WARN_UNUSED_VARIABLE = YES; 459 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 460 | MTL_ENABLE_DEBUG_INFO = YES; 461 | ONLY_ACTIVE_ARCH = YES; 462 | SDKROOT = iphoneos; 463 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 464 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 465 | SWIFT_VERSION = 4.2; 466 | }; 467 | name = Debug; 468 | }; 469 | 4CBCC1091ECDE78800B8522C /* Release */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ALWAYS_SEARCH_USER_PATHS = NO; 473 | CLANG_ANALYZER_NONNULL = YES; 474 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 475 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 476 | CLANG_CXX_LIBRARY = "libc++"; 477 | CLANG_ENABLE_MODULES = YES; 478 | CLANG_ENABLE_OBJC_ARC = YES; 479 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 480 | CLANG_WARN_BOOL_CONVERSION = YES; 481 | CLANG_WARN_COMMA = YES; 482 | CLANG_WARN_CONSTANT_CONVERSION = YES; 483 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 484 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 485 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 486 | CLANG_WARN_EMPTY_BODY = YES; 487 | CLANG_WARN_ENUM_CONVERSION = YES; 488 | CLANG_WARN_INFINITE_RECURSION = YES; 489 | CLANG_WARN_INT_CONVERSION = YES; 490 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 491 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 492 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 493 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 494 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 495 | CLANG_WARN_STRICT_PROTOTYPES = YES; 496 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 497 | CLANG_WARN_UNREACHABLE_CODE = YES; 498 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 499 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 500 | COPY_PHASE_STRIP = NO; 501 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 502 | ENABLE_NS_ASSERTIONS = NO; 503 | ENABLE_STRICT_OBJC_MSGSEND = YES; 504 | GCC_C_LANGUAGE_STANDARD = gnu99; 505 | GCC_NO_COMMON_BLOCKS = YES; 506 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 507 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 508 | GCC_WARN_UNDECLARED_SELECTOR = YES; 509 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 510 | GCC_WARN_UNUSED_FUNCTION = YES; 511 | GCC_WARN_UNUSED_VARIABLE = YES; 512 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 513 | MTL_ENABLE_DEBUG_INFO = NO; 514 | SDKROOT = iphoneos; 515 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 516 | SWIFT_VERSION = 4.2; 517 | VALIDATE_PRODUCT = YES; 518 | }; 519 | name = Release; 520 | }; 521 | 4CBCC10B1ECDE78800B8522C /* Debug */ = { 522 | isa = XCBuildConfiguration; 523 | baseConfigurationReference = A9DA607C5C71663F7F3416DD /* Pods-Passcode.debug.xcconfig */; 524 | buildSettings = { 525 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 526 | DEVELOPMENT_TEAM = 3YN6YPP3YC; 527 | INFOPLIST_FILE = Passcode/Info.plist; 528 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 529 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 530 | PRODUCT_BUNDLE_IDENTIFIER = Cruz.Passcode; 531 | PRODUCT_NAME = "$(TARGET_NAME)"; 532 | SWIFT_VERSION = 4.2; 533 | }; 534 | name = Debug; 535 | }; 536 | 4CBCC10C1ECDE78800B8522C /* Release */ = { 537 | isa = XCBuildConfiguration; 538 | baseConfigurationReference = BB1E9C33C6F9122D62082B3D /* Pods-Passcode.release.xcconfig */; 539 | buildSettings = { 540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 541 | DEVELOPMENT_TEAM = 3YN6YPP3YC; 542 | INFOPLIST_FILE = Passcode/Info.plist; 543 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 544 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 545 | PRODUCT_BUNDLE_IDENTIFIER = Cruz.Passcode; 546 | PRODUCT_NAME = "$(TARGET_NAME)"; 547 | SWIFT_VERSION = 4.2; 548 | }; 549 | name = Release; 550 | }; 551 | 4CBCC10E1ECDE78800B8522C /* Debug */ = { 552 | isa = XCBuildConfiguration; 553 | baseConfigurationReference = E8FA8563A6C27970CFE7F06F /* Pods-Passcode-PasscodeTests.debug.xcconfig */; 554 | buildSettings = { 555 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 556 | BUNDLE_LOADER = "$(TEST_HOST)"; 557 | DEVELOPMENT_TEAM = 3YN6YPP3YC; 558 | INFOPLIST_FILE = PasscodeTests/Info.plist; 559 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 560 | PRODUCT_BUNDLE_IDENTIFIER = Cruz.PasscodeTests; 561 | PRODUCT_NAME = "$(TARGET_NAME)"; 562 | SWIFT_VERSION = 4.2; 563 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passcode.app/Passcode"; 564 | }; 565 | name = Debug; 566 | }; 567 | 4CBCC10F1ECDE78800B8522C /* Release */ = { 568 | isa = XCBuildConfiguration; 569 | baseConfigurationReference = 0C5FC3B273A2F8B5A25D54C6 /* Pods-Passcode-PasscodeTests.release.xcconfig */; 570 | buildSettings = { 571 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 572 | BUNDLE_LOADER = "$(TEST_HOST)"; 573 | DEVELOPMENT_TEAM = 3YN6YPP3YC; 574 | INFOPLIST_FILE = PasscodeTests/Info.plist; 575 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 576 | PRODUCT_BUNDLE_IDENTIFIER = Cruz.PasscodeTests; 577 | PRODUCT_NAME = "$(TARGET_NAME)"; 578 | SWIFT_VERSION = 4.2; 579 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Passcode.app/Passcode"; 580 | }; 581 | name = Release; 582 | }; 583 | /* End XCBuildConfiguration section */ 584 | 585 | /* Begin XCConfigurationList section */ 586 | 4CBCC0E81ECDE78800B8522C /* Build configuration list for PBXProject "Passcode" */ = { 587 | isa = XCConfigurationList; 588 | buildConfigurations = ( 589 | 4CBCC1081ECDE78800B8522C /* Debug */, 590 | 4CBCC1091ECDE78800B8522C /* Release */, 591 | ); 592 | defaultConfigurationIsVisible = 0; 593 | defaultConfigurationName = Release; 594 | }; 595 | 4CBCC10A1ECDE78800B8522C /* Build configuration list for PBXNativeTarget "Passcode" */ = { 596 | isa = XCConfigurationList; 597 | buildConfigurations = ( 598 | 4CBCC10B1ECDE78800B8522C /* Debug */, 599 | 4CBCC10C1ECDE78800B8522C /* Release */, 600 | ); 601 | defaultConfigurationIsVisible = 0; 602 | defaultConfigurationName = Release; 603 | }; 604 | 4CBCC10D1ECDE78800B8522C /* Build configuration list for PBXNativeTarget "PasscodeTests" */ = { 605 | isa = XCConfigurationList; 606 | buildConfigurations = ( 607 | 4CBCC10E1ECDE78800B8522C /* Debug */, 608 | 4CBCC10F1ECDE78800B8522C /* Release */, 609 | ); 610 | defaultConfigurationIsVisible = 0; 611 | defaultConfigurationName = Release; 612 | }; 613 | /* End XCConfigurationList section */ 614 | }; 615 | rootObject = 4CBCC0E51ECDE78800B8522C /* Project object */; 616 | } 617 | -------------------------------------------------------------------------------- /Passcode.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Passcode.xcodeproj/xcuserdata/cruzdiary.xcuserdatad/xcschemes/Passcode.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Passcode.xcodeproj/xcuserdata/cruzdiary.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Passcode.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4CBCC0EC1ECDE78800B8522C 16 | 17 | primary 18 | 19 | 20 | 4CBCC1001ECDE78800B8522C 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Passcode.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Passcode.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Passcode/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Passcode 4 | // 5 | // Created by CruzDiary on 18/05/2017. 6 | // Copyright © 2017 Cruz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | import GSMessages 12 | 13 | @UIApplicationMain 14 | class AppDelegate: UIResponder, UIApplicationDelegate { 15 | 16 | var window: UIWindow? 17 | 18 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 19 | // Override point for customization after application launch. 20 | 21 | // GSMessages 22 | GSMessage.font = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.thin) 23 | GSMessage.infoBackgroundColor = #colorLiteral(red: 0.09956099838, green: 0.08143451065, blue: 0.4110894799, alpha: 1) 24 | GSMessage.successBackgroundColor = #colorLiteral(red: 0.8688575625, green: 0.8219094872, blue: 0.0601625368, alpha: 1) 25 | GSMessage.errorBackgroundColor = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1) 26 | 27 | return true 28 | } 29 | 30 | func applicationWillResignActive(_ application: UIApplication) { 31 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 32 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 33 | } 34 | 35 | func applicationDidEnterBackground(_ application: UIApplication) { 36 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | func applicationWillEnterForeground(_ application: UIApplication) { 41 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | func applicationDidBecomeActive(_ application: UIApplication) { 45 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 46 | } 47 | 48 | func applicationWillTerminate(_ application: UIApplication) { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /Passcode/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Passcode/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Passcode/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 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 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 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | -------------------------------------------------------------------------------- /Passcode/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Passcode/KeyCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeyCell.swift 3 | // Passcode 4 | // 5 | // Created by CruzDiary on 20/05/2017. 6 | // Copyright © 2017 Cruz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class KeyCell: UICollectionViewCell { 12 | static let nibName = "KeyCell" 13 | @IBOutlet weak var keyLabel: UILabel! 14 | } 15 | -------------------------------------------------------------------------------- /Passcode/KeyCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Passcode/KeySectionController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KeySectionController.swift 3 | // Passcode 4 | // 5 | // Created by CruzDiary on 20/05/2017. 6 | // Copyright © 2017 Cruz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | import IGListKit 12 | 13 | class Key: ListDiffable { 14 | var key: String 15 | init(key: String) { 16 | self.key = key 17 | } 18 | 19 | func diffIdentifier() -> NSObjectProtocol { 20 | return key as NSObjectProtocol 21 | } 22 | 23 | func isEqual(toDiffableObject object: ListDiffable?) -> Bool { 24 | if self === object { 25 | return true 26 | } 27 | 28 | if let key = object as? Key { 29 | return self.key == key.key 30 | } 31 | 32 | return false 33 | } 34 | } 35 | 36 | class KeySectionController: ListSectionController { 37 | var key: Key? 38 | override func sizeForItem(at index: Int) -> CGSize { 39 | guard let context = collectionContext else { return .zero } 40 | return CGSize(width: context.containerSize.width/3, height: context.containerSize.height/4) 41 | } 42 | 43 | override func cellForItem(at index: Int) -> UICollectionViewCell { 44 | guard let cell = collectionContext?.dequeueReusableCell(withNibName: KeyCell.nibName, bundle: nil, for: self, at: index) as? KeyCell else { 45 | fatalError() 46 | } 47 | cell.keyLabel.text = key?.key 48 | return cell 49 | } 50 | 51 | override func didUpdate(to object: Any) { 52 | key = object as? Key 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /Passcode/PasscodeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Passcode 4 | // 5 | // Created by CruzDiary on 18/05/2017. 6 | // Copyright © 2017 Cruz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | import GSMessages 12 | import IGListKit 13 | import Pastel 14 | import ReactorKit 15 | import RxCocoa 16 | import RxSwift 17 | 18 | class PasscodeViewController: UIViewController, View { 19 | @IBOutlet weak var generateButton: UIButton! 20 | 21 | // IGListKit 22 | lazy var adapter: ListAdapter = { 23 | return ListAdapter(updater: ListAdapterUpdater(), viewController: self) 24 | }() 25 | @IBOutlet weak var collectionView: UICollectionView! 26 | private let dataSource = DataSource() 27 | 28 | @IBOutlet var passcodeViews: [UIView]! 29 | // Rx 30 | var disposeBag = DisposeBag() 31 | 32 | var keys: [String] = [] 33 | 34 | @IBOutlet weak var pastelView: PastelView! 35 | override func viewDidLoad() { 36 | super.viewDidLoad() 37 | 38 | // ReactorKit 39 | self.reactor = PasscodeViewReactor() 40 | 41 | // IGListKit 42 | collectionView.collectionViewLayout = ListCollectionViewLayout(stickyHeaders: false, topContentInset: 0, stretchToEdge: false) 43 | adapter.collectionView = collectionView 44 | adapter.collectionViewDelegate = self 45 | 46 | // RxIGListKit 47 | adapter.rx.setDataSource(dataSource) 48 | .disposed(by: disposeBag) 49 | 50 | // Pastel 51 | pastelView.setColors([#colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1), #colorLiteral(red: 0.5568627715, green: 0.3529411852, blue: 0.9686274529, alpha: 1), #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1), #colorLiteral(red: 0.2745098174, green: 0.4862745106, blue: 0.1411764771, alpha: 1), #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1), #colorLiteral(red: 0.1921568662, green: 0.007843137719, blue: 0.09019608051, alpha: 1), #colorLiteral(red: 0.09019608051, green: 0, blue: 0.3019607961, alpha: 1)]) 52 | pastelView.animationDuration = 2.0 53 | pastelView.startAnimation() 54 | 55 | // UI 56 | passcodeViews.forEach { 57 | $0.clipsToBounds = true 58 | $0.layer.cornerRadius = 10 59 | $0.layer.borderWidth = 1.0 60 | $0.layer.borderColor = UIColor.white.cgColor 61 | $0.backgroundColor = .clear 62 | } 63 | } 64 | 65 | func bind(reactor: PasscodeViewReactor) { 66 | // Action 67 | generateButton.rx.tap 68 | .map { Reactor.Action.generate } 69 | .bind(to: reactor.action) 70 | .disposed(by: disposeBag) 71 | 72 | collectionView.rx 73 | .itemSelected 74 | .map { [weak self] in self?.adapter.object(atSection: $0.section) as? String } 75 | .map { Reactor.Action.typing(key: $0) } 76 | .bind(to: reactor.action) 77 | .disposed(by: disposeBag) 78 | 79 | // State 80 | reactor.state 81 | .map { $0.passcode } 82 | .distinctUntilChanged() 83 | .map { "😜 Password changed to \($0)" } 84 | .subscribe(onNext: { [weak self] message in 85 | self?.showMessage(message, type: .info) 86 | }) 87 | .disposed(by: disposeBag) 88 | 89 | reactor.state 90 | .map { $0.keys.map { Key(key: $0) } } 91 | .bind(to: adapter.rx.items(dataSource: dataSource)) 92 | .disposed(by: disposeBag) 93 | 94 | reactor.state 95 | .map { $0.validation } 96 | .distinctUntilChanged() 97 | .filter { $0 != .normal } 98 | .do(onNext: { [weak self](validation) in 99 | guard let s = self else { return } 100 | switch validation { 101 | case .valid: 102 | s.showMessage("Correct!!! 😜", type: .success) 103 | case .invalid: 104 | s.showMessage("InCorrect!!! 😥", type: .error) 105 | default: 106 | break 107 | } 108 | }) 109 | .delay(2.0, scheduler: MainScheduler.instance) 110 | .map { _ in PasscodeViewReactor.Action.generate } 111 | .bind(to: reactor.action) 112 | .disposed(by: disposeBag) 113 | 114 | reactor.state 115 | .map { $0.input.count } 116 | .subscribe(onNext: { [weak self] count in 117 | guard let s = self else { return } 118 | for (idx, view) in s.passcodeViews.enumerated() { 119 | view.backgroundColor = idx < count ? .white : .clear 120 | } 121 | }) 122 | .disposed(by: disposeBag) 123 | } 124 | 125 | // RxIGListKit 126 | final class DataSource: NSObject, ListAdapterDataSource, RxListAdapterDataSource { 127 | typealias Element = [Key] 128 | 129 | var elements: Element = [] 130 | 131 | func listAdapter(_ adapter: ListAdapter, observedEvent: Event<[Key]>) { 132 | if case .next(let keys) = observedEvent { 133 | elements = keys 134 | adapter.performUpdates(animated: true) 135 | } 136 | } 137 | 138 | func objects(for listAdapter: ListAdapter) -> [ListDiffable] { 139 | return elements as [ListDiffable] 140 | } 141 | 142 | func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController { 143 | return KeySectionController() 144 | } 145 | 146 | func emptyView(for listAdapter: ListAdapter) -> UIView? { 147 | return nil 148 | } 149 | } 150 | } 151 | 152 | protocol RxListAdapterDataSource { 153 | associatedtype Element 154 | func listAdapter(_ adapter: ListAdapter, observedEvent: Event) -> Void 155 | } 156 | 157 | extension PasscodeViewController: UICollectionViewDelegate { 158 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 159 | guard let object = adapter.object(atSection: indexPath.section) as? Key else { return } 160 | reactor?.action.onNext(PasscodeViewReactor.Action.typing(key: object.key)) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /Passcode/PasscodeViewReactor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasscodeReactor.swift 3 | // Passcode 4 | // 5 | // Created by CruzDiary on 19/05/2017. 6 | // Copyright © 2017 Cruz. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | import ReactorKit 12 | import RxCocoa 13 | import RxSwift 14 | 15 | class PasscodeViewReactor: Reactor { 16 | struct Constant { 17 | static let maxInput = 4 18 | } 19 | 20 | enum Action { 21 | case generate 22 | case typing(key: String?) 23 | } 24 | 25 | enum Mutation { 26 | case setInput(String) 27 | case setPasscode(String) 28 | case setKeys([String]) 29 | case setValidation(Validation) 30 | } 31 | 32 | enum Validation { 33 | case normal 34 | case valid 35 | case invalid 36 | } 37 | 38 | struct State { 39 | var passcode: String 40 | var input: String 41 | var keys: [String] 42 | var validation: Validation 43 | } 44 | 45 | let initialState = State(passcode: "0000", 46 | input: "", 47 | keys: (0...9).map { "\($0)" } + ["<"], 48 | validation: .normal) 49 | 50 | func mutate(action: Action) -> Observable { 51 | switch action { 52 | case .generate: 53 | return Observable.from([ 54 | Mutation.setInput(""), 55 | Mutation.setPasscode(generatePasscode()), 56 | Mutation.setKeys(shuffleKeys()), 57 | Mutation.setValidation(.normal) 58 | ]) 59 | case .typing(let key): 60 | guard let key = key, currentState.validation == .normal else { return .empty() } 61 | let nextKeys = shuffleKeys() 62 | switch key { 63 | case "0"..."9": 64 | return state.take(1) 65 | .map { ($0.input + key, $0.passcode) } 66 | .flatMap { (input, passcode) -> Observable in 67 | return Observable.from([ 68 | Mutation.setInput(input), 69 | input.count == Constant.maxInput ? (Mutation.setValidation(input == passcode ? .valid : .invalid)) : Mutation.setKeys(nextKeys) 70 | ]) 71 | } 72 | case "<": 73 | return state.take(1) 74 | .map { $0.input } 75 | .filter { $0.count > 0 } 76 | .flatMap { input -> Observable in 77 | return Observable.from([ 78 | Mutation.setInput(String(input.prefix(input.count - 1))), 79 | Mutation.setKeys(nextKeys) 80 | ]) 81 | } 82 | default: 83 | return .empty() 84 | } 85 | } 86 | } 87 | 88 | func reduce(state: State, mutation: Mutation) -> State { 89 | var newState = state 90 | switch mutation { 91 | case .setInput(let input): 92 | newState.input = input 93 | case .setPasscode(let passcode): 94 | newState.passcode = passcode 95 | case .setKeys(let keys): 96 | newState.keys = keys 97 | case .setValidation(let validation): 98 | newState.validation = validation 99 | } 100 | return newState 101 | } 102 | 103 | func generatePasscode() -> String { 104 | return String((0 ..< Constant.maxInput).map { _ in Character("\(arc4random() % 10)") }) 105 | } 106 | 107 | func shuffleKeys() -> [String] { 108 | let keys = (0...9).map { "\($0)" } + ["<"] 109 | return keys.shuffled() 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /Passcode/RxIGListAdapterDataSource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RxIGListAdapterDataSource.swift 3 | // RxIGListKit 4 | // 5 | // Created by yuzushioh on 2017/04/09. 6 | // Copyright © 2017 yuzushioh. All rights reserved. 7 | // 8 | 9 | import RxSwift 10 | import IGListKit 11 | import RxCocoa 12 | 13 | extension Reactive where Base: ListAdapter { 14 | func items(dataSource: DataSource) 15 | -> (_ source: O) 16 | -> Disposable where DataSource.Element == O.E { 17 | 18 | return { source in 19 | let subscription = source 20 | .subscribe { dataSource.listAdapter(self.base, observedEvent: $0) } 21 | 22 | return Disposables.create { 23 | subscription.dispose() 24 | } 25 | } 26 | } 27 | 28 | func setDataSource(_ dataSource: DataSource) -> Disposable { 29 | base.dataSource = dataSource 30 | return Disposables.create() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /PasscodeTests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /PasscodeTests/PasscodeTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PasscodeTests.swift 3 | // PasscodeTests 4 | // 5 | // Created by CruzDiary on 18/05/2017. 6 | // Copyright © 2017 Cruz. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Passcode 11 | 12 | class PasscodeTests: XCTestCase { 13 | override func setUp() { 14 | super.setUp() 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | super.tearDown() 21 | } 22 | 23 | func testExample() { 24 | // This is an example of a functional test case. 25 | // Use XCTAssert and related functions to verify your tests produce the correct results. 26 | } 27 | 28 | func testPerformanceExample() { 29 | // This is an example of a performance test case. 30 | self.measure { 31 | // Put the code you want to measure the time of here. 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | inhibit_all_warnings! 3 | 4 | target 'Passcode' do 5 | use_frameworks! 6 | 7 | pod 'DeviceLayout', '= 0.4.0' 8 | pod 'GSMessages', '= 1.6.1' 9 | pod 'IGListKit', '= 3.4.0' 10 | pod 'Pastel', '= 0.5.1' 11 | pod 'ReactorKit', '= 1.2.1' 12 | pod 'RxCocoa', '= 4.3.1' 13 | pod 'RxSwift', '= 4.3.1' 14 | 15 | target 'PasscodeTests' do 16 | inherit! :complete 17 | 18 | pod 'RxTest', '= 4.3.1' 19 | pod 'RxExpect', '= 1.1.0' 20 | end 21 | end 22 | 23 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Device (3.1.2) 3 | - DeviceLayout (0.4.0): 4 | - Device (~> 3.1.2) 5 | - GSMessages (1.6.1) 6 | - IGListKit (3.4.0): 7 | - IGListKit/Default (= 3.4.0) 8 | - IGListKit/Default (3.4.0): 9 | - IGListKit/Diffing 10 | - IGListKit/Diffing (3.4.0) 11 | - Pastel (0.5.1) 12 | - ReactorKit (1.2.1): 13 | - RxSwift (>= 4.0.0) 14 | - RxCocoa (4.3.1): 15 | - RxSwift (~> 4.0) 16 | - RxExpect (1.1.0): 17 | - RxCocoa (>= 4.0.0) 18 | - RxSwift (>= 4.0.0) 19 | - RxTest (>= 4.0.0) 20 | - RxSwift (4.3.1) 21 | - RxTest (4.3.1): 22 | - RxSwift (~> 4.0) 23 | 24 | DEPENDENCIES: 25 | - DeviceLayout (= 0.4.0) 26 | - GSMessages (= 1.6.1) 27 | - IGListKit (= 3.4.0) 28 | - Pastel (= 0.5.1) 29 | - ReactorKit (= 1.2.1) 30 | - RxCocoa (= 4.3.1) 31 | - RxExpect (= 1.1.0) 32 | - RxSwift (= 4.3.1) 33 | - RxTest (= 4.3.1) 34 | 35 | SPEC REPOS: 36 | https://github.com/cocoapods/specs.git: 37 | - Device 38 | - DeviceLayout 39 | - GSMessages 40 | - IGListKit 41 | - Pastel 42 | - ReactorKit 43 | - RxCocoa 44 | - RxExpect 45 | - RxSwift 46 | - RxTest 47 | 48 | SPEC CHECKSUMS: 49 | Device: 62242076214c30fb5760174b3601cefafa70a481 50 | DeviceLayout: 3db697bd179787b79b54d7adfe09f73403e53e80 51 | GSMessages: 870aa0fc8cf39bea0026535ea195376d4040313e 52 | IGListKit: 7a5d788e9fb746bcd402baa8e8b24bc3bd2a5a07 53 | Pastel: b3dd5b8d612dac06ae7c63c97c45c900829bc139 54 | ReactorKit: 8be57f0527ad1ac2963cd5c338274a46a01e57a3 55 | RxCocoa: 78763c7b07d02455598d9fc3c1ad091a28b73635 56 | RxExpect: 618ecd84f07b644e9fb436e1a0ec39363caa22b2 57 | RxSwift: fe0fd770a43acdb7d0a53da411c9b892e69bb6e4 58 | RxTest: ea97a208826906f3904c0debdd09575ebcbfe216 59 | 60 | PODFILE CHECKSUM: 9c765d617efbe3d3bce712db28c6574d7e595bc6 61 | 62 | COCOAPODS: 1.6.0.beta.1 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # passcode 2 | 🔑 Passcode for iOS ReactorKit, IGListKit 3 | 4 | ![Swift](https://img.shields.io/badge/Swift-4.2-orange.svg) 5 | 6 | ![passcode1](https://media.giphy.com/media/pfOZFhFBI8gla/giphy.gif) 7 | ![passcode2](https://media.giphy.com/media/XUNTYzNSC25aM/giphy.gif) 8 | 9 | ## Features 10 | 11 | * Using [DeviceLayout](https://github.com/cruisediary/DeviceLayout) AutoLayout can be set differently for each device 12 | * Using [GSMessage](https://github.com/wxxsw/GSMessages) A simple style messages/notifications, in Swift. 13 | * Using [ReactorKit](https://github.com/devxoul/ReactorKit) A framework for reactive and unidirectional Swift application architecture 14 | * Using [IGListKit](https://github.com/Instagram/IGListKit) A data-driven UICollectionView framework for building fast and flexible lists. 15 | * Using [RxIGListKit](https://github.com/yuzushioh/RxIGListKit) IGListKit with RxSwift🚀 16 | * Using [Pastel](https://github.com/cruisediary/Pastel) 🎨 Gradient animation effect like Instagram 17 | 18 | 19 | ## Requirements 20 | 21 | * iOS 9+ 22 | * Swift 4.2 23 | * CocoaPods 1.5.3 24 | 25 | ## Author 26 | 27 | cruz, cruzdiary@gmail.com 28 | 29 | ## License 30 | 31 | Passcode is available under the MIT license. See the LICENSE file for more info. 32 | --------------------------------------------------------------------------------