├── .codecov.yml ├── .gitattributes ├── .gitignore ├── .hound.yml ├── .ruby-gemset ├── .ruby-version ├── .swiftlint.yml ├── .travis.yml ├── CHANGELOG.yml ├── Cartfile ├── Cartfile.private ├── Cartfile.resolved ├── Core ├── Core.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── Core.xcscheme ├── Core │ ├── Configurations │ │ ├── Builds │ │ │ ├── Debug.xcconfig │ │ │ ├── DebugTest.xcconfig │ │ │ ├── Framework.xcconfig │ │ │ ├── Release.xcconfig │ │ │ ├── ReleaseTest.xcconfig │ │ │ ├── Shared.xcconfig │ │ │ └── SharedTest.xcconfig │ │ └── Info.plist │ ├── Core.h │ └── Core.swift └── CoreTests │ ├── Configurations │ └── Info.plist │ └── Tests │ └── CoreTests.swift ├── Dangerfile ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Makefile ├── README.md ├── documentation └── images │ ├── app-store-connect-user.png │ ├── codecov-report.png │ ├── danger-bot-note.png │ ├── hockeyapp-app-token.png │ ├── hockeyapp-dashboard.png │ ├── hockeyapp-download-site.png │ ├── houndci-warning.png │ ├── ios-project-template-logo.png │ ├── travis-ci-environment-variables.png │ ├── travis-ci-repository-selection.png │ ├── xcode-build-settings-xcconfig.png │ ├── xcode-code-coverage.png │ ├── xcode-embedded-binaries.png │ ├── xcode-framework-carthage-linking.png │ ├── xcode-main-interface-reference.png │ ├── xcode-project-configuration.png │ ├── xcode-project-structure.png │ ├── xcode-swiftlint-warnings.png │ └── xcode-xcconfig-files.png ├── fastlane ├── .gitignore ├── Fastfile ├── README.md └── libs │ ├── encryption.rb │ └── signing.rb ├── iOSProject.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── iOSProject.xcscheme ├── iOSProject.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── iOSProject ├── AppDelegate.swift ├── Configurations │ ├── Builds │ │ ├── Application.xcconfig │ │ ├── Debug.xcconfig │ │ ├── DebugTest.xcconfig │ │ ├── Release.xcconfig │ │ ├── ReleaseTest.xcconfig │ │ ├── Shared.xcconfig │ │ ├── SharedTest.xcconfig │ │ ├── Signing │ │ │ ├── DebugSigning.xcconfig │ │ │ ├── ReleaseSigning.xcconfig │ │ │ ├── SharedSigning.xcconfig │ │ │ └── StagingSigning.xcconfig │ │ ├── Staging.xcconfig │ │ └── StagingTest.xcconfig │ └── Info.plist ├── Resources │ ├── Assests.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-40.png │ │ │ ├── Icon-40@2x.png │ │ │ ├── Icon-40@3x.png │ │ │ ├── Icon-60@2x.png │ │ │ ├── Icon-60@3x.png │ │ │ ├── Icon-72.png │ │ │ ├── Icon-72@2x.png │ │ │ ├── Icon-76.png │ │ │ ├── Icon-76@2x.png │ │ │ ├── Icon-83.5@2x.png │ │ │ ├── Icon-Small-50.png │ │ │ ├── Icon-Small-50@2x.png │ │ │ ├── Icon-Small.png │ │ │ ├── Icon-Small@2x.png │ │ │ ├── Icon-Small@3x.png │ │ │ ├── Icon.png │ │ │ ├── Icon@2x.png │ │ │ ├── NotificationIcon@2x.png │ │ │ ├── NotificationIcon@3x.png │ │ │ ├── NotificationIcon~ipad.png │ │ │ ├── NotificationIcon~ipad@2x.png │ │ │ └── ios-marketing.png │ │ └── Contents.json │ └── LaunchScreen.storyboard ├── Scenes │ └── .gitignore └── main.swift ├── iOSProjectTests ├── Configurations │ └── Info.plist └── Tests │ └── iOSProjectTests.swift └── signing ├── .gitignore ├── release ├── certificate.p12.enc └── provisioning-profile.mobileprovision.enc └── staging ├── certificate.p12.enc └── provisioning-profile.mobileprovision.enc /.codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | branch: master 3 | 4 | coverage: 5 | status: 6 | project: 7 | default: off 8 | ios: 9 | flags: ios 10 | core: 11 | flags: core 12 | 13 | flags: 14 | ios: 15 | paths: 16 | - iOSProject/iOSProject/ 17 | core: 18 | paths: 19 | - Core/Core/ 20 | 21 | ignore: 22 | - "iOSProjectTests/.*" 23 | - "Core/CoreTests/.*" 24 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Keeps ours and theirs changes to avoid merge conflicts 2 | CHANGELOG.yml merge=union 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | .DS_Store 3 | 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData/ 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata/ 22 | 23 | ## Other 24 | *.moved-aside 25 | *.xccheckout 26 | *.xcscmblueprint 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | *.dSYM.zip 32 | *.dSYM 33 | 34 | ## Playgrounds 35 | timeline.xctimeline 36 | playground.xcworkspace 37 | 38 | # Swift Package Manager 39 | # 40 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 41 | # Packages/ 42 | # Package.pins 43 | # Package.resolved 44 | .build/ 45 | 46 | # CocoaPods 47 | # 48 | # We recommend against adding the Pods directory to your .gitignore. However 49 | # you should judge for yourself, the pros and cons are mentioned at: 50 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 51 | # 52 | # Pods/ 53 | 54 | # Carthage 55 | # 56 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 57 | # Carthage/Checkouts 58 | 59 | Carthage/* 60 | 61 | # fastlane 62 | # 63 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 64 | # screenshots whenever they are needed. 65 | # For more information about the recommended setup visit: 66 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 67 | 68 | fastlane/report.xml 69 | fastlane/Preview.html 70 | fastlane/screenshots 71 | fastlane/test_output 72 | 73 | # Configuration Repository 74 | /Configuration/ 75 | /Ambidexter/Configuration/Files/* 76 | !/Ambidexter/Configuration/Files/README.md 77 | !/Ambidexter/Configuration/Files/*.template 78 | -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | swift: 2 | enabled: true 3 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | iosproject 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.5.1 2 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: # rule identifiers to exclude from running 2 | 3 | opt_in_rules: # some rules are only opt-in 4 | - attributes 5 | - closure_end_indentation 6 | - closure_spacing 7 | - conditional_returns_on_newline 8 | - empty_count 9 | - explicit_init 10 | # Use type inference 11 | # - explicit_type_interface 12 | # Disabled, because Extensions in external Frameworks needs public access 13 | # - extension_access_modifier 14 | - fatal_error_message 15 | - force_unwrapping 16 | # - explicit_top_level_acl 17 | # - file_header 18 | - first_where 19 | - implicit_return 20 | - implicitly_unwrapped_optional 21 | - let_var_whitespace 22 | - multiline_parameters 23 | - nimble_operator 24 | # - no_extension_access_modifier 25 | - number_separator 26 | - object_literal 27 | - operator_usage_whitespace 28 | - overridden_super_call 29 | - private_outlet 30 | - prohibited_super_call 31 | - redundant_nil_coalescing 32 | # - sorted_imports 33 | - strict_fileprivate 34 | - switch_case_on_newline 35 | - trailing_closure 36 | - unneeded_parentheses_in_closure_argument 37 | - vertical_parameter_alignment_on_call 38 | # Find all the available rules by running: 39 | # swiftlint rules 40 | included: # paths to include during linting. `--path` is ignored if present. 41 | - iOSProject 42 | - iOSProjectTests 43 | - Core/Core 44 | - Core/CoreTests 45 | 46 | 47 | excluded: 48 | - Carthage 49 | 50 | identifier_name: 51 | min_length: 2 52 | max_length: 53 | warning: 40 54 | error: 50 55 | 56 | line_length: 140 57 | 58 | type_body_length: 59 | warning: 200 60 | error: 400 61 | 62 | file_length: 63 | warning: 500 64 | error: 750 65 | 66 | type_name: 67 | min_length: 4 68 | max_length: 69 | warning: 40 70 | error: 50 71 | 72 | implicitly_unwrapped_optional: 73 | severity: error 74 | 75 | reporter: "xcode" 76 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode11 3 | 4 | cache: 5 | bundler: true 6 | directories: 7 | - $HOME/.rvm/ 8 | - $HOME/Library/Caches/Homebrew 9 | - $TRAVIS_BUILD_DIR/Carthage 10 | 11 | install: make setup 12 | 13 | stages: 14 | - build 15 | 16 | jobs: 17 | include: 18 | - name: Pull Request 19 | if: type = pull_request 20 | stage: build 21 | script: make pull_request 22 | - name: Staging 23 | if: branch = master AND NOT (type = pull_request) 24 | stage: build 25 | script: make staging 26 | - name: Release 27 | if: tag IS present 28 | stage: build 29 | script: make release 30 | -------------------------------------------------------------------------------- /CHANGELOG.yml: -------------------------------------------------------------------------------- 1 | - version: 0.0.2 2 | date: 3 | summary: Update to Swift 5 (Xcode 11 / iOS 13 SDK) 4 | notes: 5 | - version: 0.0.1 6 | date: 7 | summary: Adds base project 8 | notes: 9 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "Alamofire/Alamofire" ~> 4.9 2 | -------------------------------------------------------------------------------- /Cartfile.private: -------------------------------------------------------------------------------- 1 | github "Quick/Quick" ~> 2.1 2 | github "Quick/Nimble" ~> 8.0.4 3 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "Alamofire/Alamofire" "4.9.0" 2 | github "Quick/Nimble" "v8.0.4" 3 | github "Quick/Quick" "v2.1.0" 4 | -------------------------------------------------------------------------------- /Core/Core.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E0C82F4921478BC0009EA559 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E0C82F28214789D8009EA559 /* Alamofire.framework */; }; 11 | E0C82F4B21478DCC009EA559 /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C82F4A21478DCC009EA559 /* Core.swift */; }; 12 | E0FD11E721477A5F008C2EF8 /* Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E0FD11DD21477A5F008C2EF8 /* Core.framework */; }; 13 | E0FD11EE21477A5F008C2EF8 /* Core.h in Headers */ = {isa = PBXBuildFile; fileRef = E0FD11E021477A5F008C2EF8 /* Core.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | E0FD1235214786F6008C2EF8 /* CoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0FD1234214786F6008C2EF8 /* CoreTests.swift */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXContainerItemProxy section */ 18 | E0FD11E821477A5F008C2EF8 /* PBXContainerItemProxy */ = { 19 | isa = PBXContainerItemProxy; 20 | containerPortal = E0FD11D421477A5F008C2EF8 /* Project object */; 21 | proxyType = 1; 22 | remoteGlobalIDString = E0FD11DC21477A5F008C2EF8; 23 | remoteInfo = Core; 24 | }; 25 | /* End PBXContainerItemProxy section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | E0C82F28214789D8009EA559 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = ../Carthage/Build/iOS/Alamofire.framework; sourceTree = ""; }; 29 | E0C82F4A21478DCC009EA559 /* Core.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Core.swift; sourceTree = ""; }; 30 | E0FD11DD21477A5F008C2EF8 /* Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Core.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | E0FD11E021477A5F008C2EF8 /* Core.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Core.h; sourceTree = ""; }; 32 | E0FD11E621477A5F008C2EF8 /* CoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | E0FD1227214784F5008C2EF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | E0FD1229214786AD008C2EF8 /* DebugTest.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DebugTest.xcconfig; sourceTree = ""; }; 35 | E0FD122A214786AD008C2EF8 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 36 | E0FD122B214786AD008C2EF8 /* SharedTest.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SharedTest.xcconfig; sourceTree = ""; }; 37 | E0FD122C214786AD008C2EF8 /* Framework.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Framework.xcconfig; sourceTree = ""; }; 38 | E0FD122D214786AE008C2EF8 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = ""; }; 39 | E0FD122E214786AE008C2EF8 /* Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; 40 | E0FD122F214786AE008C2EF8 /* ReleaseTest.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = ReleaseTest.xcconfig; sourceTree = ""; }; 41 | E0FD1232214786EF008C2EF8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | E0FD1234214786F6008C2EF8 /* CoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreTests.swift; sourceTree = ""; }; 43 | /* End PBXFileReference section */ 44 | 45 | /* Begin PBXFrameworksBuildPhase section */ 46 | E0FD11DA21477A5F008C2EF8 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | E0C82F4921478BC0009EA559 /* Alamofire.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | E0FD11E321477A5F008C2EF8 /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | E0FD11E721477A5F008C2EF8 /* Core.framework in Frameworks */, 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | E0C82F27214789D8009EA559 /* Frameworks */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | E0C82F28214789D8009EA559 /* Alamofire.framework */, 69 | ); 70 | name = Frameworks; 71 | sourceTree = ""; 72 | }; 73 | E0FD11D321477A5F008C2EF8 = { 74 | isa = PBXGroup; 75 | children = ( 76 | E0FD11DF21477A5F008C2EF8 /* Core */, 77 | E0FD11EA21477A5F008C2EF8 /* CoreTests */, 78 | E0FD11DE21477A5F008C2EF8 /* Products */, 79 | E0C82F27214789D8009EA559 /* Frameworks */, 80 | ); 81 | sourceTree = ""; 82 | }; 83 | E0FD11DE21477A5F008C2EF8 /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | E0FD11DD21477A5F008C2EF8 /* Core.framework */, 87 | E0FD11E621477A5F008C2EF8 /* CoreTests.xctest */, 88 | ); 89 | name = Products; 90 | sourceTree = ""; 91 | }; 92 | E0FD11DF21477A5F008C2EF8 /* Core */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | E0FD1225214784D5008C2EF8 /* Configurations */, 96 | E0FD11E021477A5F008C2EF8 /* Core.h */, 97 | E0C82F4A21478DCC009EA559 /* Core.swift */, 98 | ); 99 | path = Core; 100 | sourceTree = ""; 101 | }; 102 | E0FD11EA21477A5F008C2EF8 /* CoreTests */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | E0FD1231214786CD008C2EF8 /* Tests */, 106 | E0FD1230214786C5008C2EF8 /* Configurations */, 107 | ); 108 | path = CoreTests; 109 | sourceTree = ""; 110 | }; 111 | E0FD1225214784D5008C2EF8 /* Configurations */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | E0FD1228214784F7008C2EF8 /* Builds */, 115 | E0FD1227214784F5008C2EF8 /* Info.plist */, 116 | ); 117 | path = Configurations; 118 | sourceTree = ""; 119 | }; 120 | E0FD1228214784F7008C2EF8 /* Builds */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | E0FD122C214786AD008C2EF8 /* Framework.xcconfig */, 124 | E0FD122E214786AE008C2EF8 /* Debug.xcconfig */, 125 | E0FD1229214786AD008C2EF8 /* DebugTest.xcconfig */, 126 | E0FD122A214786AD008C2EF8 /* Release.xcconfig */, 127 | E0FD122F214786AE008C2EF8 /* ReleaseTest.xcconfig */, 128 | E0FD122D214786AE008C2EF8 /* Shared.xcconfig */, 129 | E0FD122B214786AD008C2EF8 /* SharedTest.xcconfig */, 130 | ); 131 | path = Builds; 132 | sourceTree = ""; 133 | }; 134 | E0FD1230214786C5008C2EF8 /* Configurations */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | E0FD1232214786EF008C2EF8 /* Info.plist */, 138 | ); 139 | path = Configurations; 140 | sourceTree = ""; 141 | }; 142 | E0FD1231214786CD008C2EF8 /* Tests */ = { 143 | isa = PBXGroup; 144 | children = ( 145 | E0FD1234214786F6008C2EF8 /* CoreTests.swift */, 146 | ); 147 | path = Tests; 148 | sourceTree = ""; 149 | }; 150 | /* End PBXGroup section */ 151 | 152 | /* Begin PBXHeadersBuildPhase section */ 153 | E0FD11D821477A5F008C2EF8 /* Headers */ = { 154 | isa = PBXHeadersBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | E0FD11EE21477A5F008C2EF8 /* Core.h in Headers */, 158 | ); 159 | runOnlyForDeploymentPostprocessing = 0; 160 | }; 161 | /* End PBXHeadersBuildPhase section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | E0FD11DC21477A5F008C2EF8 /* Core */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = E0FD11F121477A5F008C2EF8 /* Build configuration list for PBXNativeTarget "Core" */; 167 | buildPhases = ( 168 | E0FD11D821477A5F008C2EF8 /* Headers */, 169 | E0FD11D921477A5F008C2EF8 /* Sources */, 170 | E0FD11DA21477A5F008C2EF8 /* Frameworks */, 171 | E0FD11DB21477A5F008C2EF8 /* Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | ); 177 | name = Core; 178 | productName = Core; 179 | productReference = E0FD11DD21477A5F008C2EF8 /* Core.framework */; 180 | productType = "com.apple.product-type.framework"; 181 | }; 182 | E0FD11E521477A5F008C2EF8 /* CoreTests */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = E0FD11F421477A5F008C2EF8 /* Build configuration list for PBXNativeTarget "CoreTests" */; 185 | buildPhases = ( 186 | E0FD11E221477A5F008C2EF8 /* Sources */, 187 | E0FD11E321477A5F008C2EF8 /* Frameworks */, 188 | E0FD11E421477A5F008C2EF8 /* Resources */, 189 | ); 190 | buildRules = ( 191 | ); 192 | dependencies = ( 193 | E0FD11E921477A5F008C2EF8 /* PBXTargetDependency */, 194 | ); 195 | name = CoreTests; 196 | productName = CoreTests; 197 | productReference = E0FD11E621477A5F008C2EF8 /* CoreTests.xctest */; 198 | productType = "com.apple.product-type.bundle.unit-test"; 199 | }; 200 | /* End PBXNativeTarget section */ 201 | 202 | /* Begin PBXProject section */ 203 | E0FD11D421477A5F008C2EF8 /* Project object */ = { 204 | isa = PBXProject; 205 | attributes = { 206 | LastSwiftUpdateCheck = 1000; 207 | LastUpgradeCheck = 1100; 208 | ORGANIZATIONNAME = messeb.com; 209 | TargetAttributes = { 210 | E0FD11DC21477A5F008C2EF8 = { 211 | CreatedOnToolsVersion = 10.0; 212 | LastSwiftMigration = 1100; 213 | }; 214 | E0FD11E521477A5F008C2EF8 = { 215 | CreatedOnToolsVersion = 10.0; 216 | LastSwiftMigration = 1100; 217 | }; 218 | }; 219 | }; 220 | buildConfigurationList = E0FD11D721477A5F008C2EF8 /* Build configuration list for PBXProject "Core" */; 221 | compatibilityVersion = "Xcode 10.0"; 222 | developmentRegion = en; 223 | hasScannedForEncodings = 0; 224 | knownRegions = ( 225 | en, 226 | Base, 227 | ); 228 | mainGroup = E0FD11D321477A5F008C2EF8; 229 | productRefGroup = E0FD11DE21477A5F008C2EF8 /* Products */; 230 | projectDirPath = ""; 231 | projectRoot = ""; 232 | targets = ( 233 | E0FD11DC21477A5F008C2EF8 /* Core */, 234 | E0FD11E521477A5F008C2EF8 /* CoreTests */, 235 | ); 236 | }; 237 | /* End PBXProject section */ 238 | 239 | /* Begin PBXResourcesBuildPhase section */ 240 | E0FD11DB21477A5F008C2EF8 /* Resources */ = { 241 | isa = PBXResourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | E0FD11E421477A5F008C2EF8 /* Resources */ = { 248 | isa = PBXResourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | ); 252 | runOnlyForDeploymentPostprocessing = 0; 253 | }; 254 | /* End PBXResourcesBuildPhase section */ 255 | 256 | /* Begin PBXSourcesBuildPhase section */ 257 | E0FD11D921477A5F008C2EF8 /* Sources */ = { 258 | isa = PBXSourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | E0C82F4B21478DCC009EA559 /* Core.swift in Sources */, 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | }; 265 | E0FD11E221477A5F008C2EF8 /* Sources */ = { 266 | isa = PBXSourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | E0FD1235214786F6008C2EF8 /* CoreTests.swift in Sources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | /* End PBXSourcesBuildPhase section */ 274 | 275 | /* Begin PBXTargetDependency section */ 276 | E0FD11E921477A5F008C2EF8 /* PBXTargetDependency */ = { 277 | isa = PBXTargetDependency; 278 | target = E0FD11DC21477A5F008C2EF8 /* Core */; 279 | targetProxy = E0FD11E821477A5F008C2EF8 /* PBXContainerItemProxy */; 280 | }; 281 | /* End PBXTargetDependency section */ 282 | 283 | /* Begin XCBuildConfiguration section */ 284 | E01BC7142148D80F004BB3A4 /* Staging */ = { 285 | isa = XCBuildConfiguration; 286 | baseConfigurationReference = E0FD122C214786AD008C2EF8 /* Framework.xcconfig */; 287 | buildSettings = { 288 | CURRENT_PROJECT_VERSION = 1; 289 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 290 | MTL_ENABLE_DEBUG_INFO = NO; 291 | MTL_FAST_MATH = YES; 292 | SWIFT_COMPILATION_MODE = wholemodule; 293 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 294 | VALIDATE_PRODUCT = YES; 295 | }; 296 | name = Staging; 297 | }; 298 | E01BC7152148D80F004BB3A4 /* Staging */ = { 299 | isa = XCBuildConfiguration; 300 | baseConfigurationReference = E0FD122A214786AD008C2EF8 /* Release.xcconfig */; 301 | buildSettings = { 302 | APPLICATION_EXTENSION_API_ONLY = YES; 303 | CLANG_ENABLE_MODULES = YES; 304 | CODE_SIGN_IDENTITY = ""; 305 | DEFINES_MODULE = YES; 306 | SWIFT_VERSION = 5.0; 307 | }; 308 | name = Staging; 309 | }; 310 | E01BC7162148D80F004BB3A4 /* Staging */ = { 311 | isa = XCBuildConfiguration; 312 | baseConfigurationReference = E0FD122F214786AE008C2EF8 /* ReleaseTest.xcconfig */; 313 | buildSettings = { 314 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 315 | SWIFT_VERSION = 5.0; 316 | }; 317 | name = Staging; 318 | }; 319 | E01BC7172148D93A004BB3A4 /* Release */ = { 320 | isa = XCBuildConfiguration; 321 | baseConfigurationReference = E0FD122C214786AD008C2EF8 /* Framework.xcconfig */; 322 | buildSettings = { 323 | CURRENT_PROJECT_VERSION = 1; 324 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 325 | MTL_ENABLE_DEBUG_INFO = NO; 326 | MTL_FAST_MATH = YES; 327 | SWIFT_COMPILATION_MODE = wholemodule; 328 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 329 | VALIDATE_PRODUCT = YES; 330 | }; 331 | name = Release; 332 | }; 333 | E01BC7182148D93A004BB3A4 /* Release */ = { 334 | isa = XCBuildConfiguration; 335 | baseConfigurationReference = E0FD122A214786AD008C2EF8 /* Release.xcconfig */; 336 | buildSettings = { 337 | APPLICATION_EXTENSION_API_ONLY = YES; 338 | CLANG_ENABLE_MODULES = YES; 339 | CODE_SIGN_IDENTITY = ""; 340 | DEFINES_MODULE = YES; 341 | SWIFT_VERSION = 5.0; 342 | }; 343 | name = Release; 344 | }; 345 | E01BC7192148D93A004BB3A4 /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | baseConfigurationReference = E0FD122F214786AE008C2EF8 /* ReleaseTest.xcconfig */; 348 | buildSettings = { 349 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 350 | SWIFT_VERSION = 5.0; 351 | }; 352 | name = Release; 353 | }; 354 | E0FD11EF21477A5F008C2EF8 /* Debug */ = { 355 | isa = XCBuildConfiguration; 356 | baseConfigurationReference = E0FD122C214786AD008C2EF8 /* Framework.xcconfig */; 357 | buildSettings = { 358 | CURRENT_PROJECT_VERSION = 1; 359 | DEBUG_INFORMATION_FORMAT = dwarf; 360 | ENABLE_TESTABILITY = YES; 361 | GCC_OPTIMIZATION_LEVEL = 0; 362 | GCC_PREPROCESSOR_DEFINITIONS = ( 363 | "DEBUG=1", 364 | "$(inherited)", 365 | ); 366 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 367 | MTL_FAST_MATH = YES; 368 | ONLY_ACTIVE_ARCH = YES; 369 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 370 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 371 | }; 372 | name = Debug; 373 | }; 374 | E0FD11F221477A5F008C2EF8 /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | baseConfigurationReference = E0FD122E214786AE008C2EF8 /* Debug.xcconfig */; 377 | buildSettings = { 378 | APPLICATION_EXTENSION_API_ONLY = YES; 379 | CLANG_ENABLE_MODULES = YES; 380 | CODE_SIGN_IDENTITY = ""; 381 | DEFINES_MODULE = YES; 382 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 383 | SWIFT_VERSION = 5.0; 384 | }; 385 | name = Debug; 386 | }; 387 | E0FD11F521477A5F008C2EF8 /* Debug */ = { 388 | isa = XCBuildConfiguration; 389 | baseConfigurationReference = E0FD1229214786AD008C2EF8 /* DebugTest.xcconfig */; 390 | buildSettings = { 391 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 392 | SWIFT_VERSION = 5.0; 393 | }; 394 | name = Debug; 395 | }; 396 | /* End XCBuildConfiguration section */ 397 | 398 | /* Begin XCConfigurationList section */ 399 | E0FD11D721477A5F008C2EF8 /* Build configuration list for PBXProject "Core" */ = { 400 | isa = XCConfigurationList; 401 | buildConfigurations = ( 402 | E0FD11EF21477A5F008C2EF8 /* Debug */, 403 | E01BC7142148D80F004BB3A4 /* Staging */, 404 | E01BC7172148D93A004BB3A4 /* Release */, 405 | ); 406 | defaultConfigurationIsVisible = 0; 407 | defaultConfigurationName = Release; 408 | }; 409 | E0FD11F121477A5F008C2EF8 /* Build configuration list for PBXNativeTarget "Core" */ = { 410 | isa = XCConfigurationList; 411 | buildConfigurations = ( 412 | E0FD11F221477A5F008C2EF8 /* Debug */, 413 | E01BC7152148D80F004BB3A4 /* Staging */, 414 | E01BC7182148D93A004BB3A4 /* Release */, 415 | ); 416 | defaultConfigurationIsVisible = 0; 417 | defaultConfigurationName = Release; 418 | }; 419 | E0FD11F421477A5F008C2EF8 /* Build configuration list for PBXNativeTarget "CoreTests" */ = { 420 | isa = XCConfigurationList; 421 | buildConfigurations = ( 422 | E0FD11F521477A5F008C2EF8 /* Debug */, 423 | E01BC7162148D80F004BB3A4 /* Staging */, 424 | E01BC7192148D93A004BB3A4 /* Release */, 425 | ); 426 | defaultConfigurationIsVisible = 0; 427 | defaultConfigurationName = Release; 428 | }; 429 | /* End XCConfigurationList section */ 430 | }; 431 | rootObject = E0FD11D421477A5F008C2EF8 /* Project object */; 432 | } 433 | -------------------------------------------------------------------------------- /Core/Core.xcodeproj/xcshareddata/xcschemes/Core.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Builds/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Shared.xcconfig" 2 | 3 | // Architectures 4 | ONLY_ACTIVE_ARCH = YES 5 | 6 | // Build Options 7 | DEBUG_INFORMATION_FORMAT = dwarf 8 | ENABLE_TESTABILITY = YES 9 | 10 | // Apple LLVM 9.0 - Code Generation 11 | GCC_OPTIMIZATION_LEVEL = 0 12 | 13 | // Apple LLVM 9.0 - Preprocessing 14 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited) 15 | 16 | // Swift Compiler - Custom Flags 17 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG 18 | 19 | // Swift Compiler - Code Generation 20 | MTL_ENABLE_DEBUG_INFO = YES 21 | 22 | // User-Defined 23 | SWIFT_OPTIMIZATION_LEVEL = -Onone 24 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Builds/DebugTest.xcconfig: -------------------------------------------------------------------------------- 1 | #include "SharedTest.xcconfig" 2 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Builds/Framework.xcconfig: -------------------------------------------------------------------------------- 1 | // Architectures 2 | SDKROOT = iphoneos 3 | 4 | // Deployment 5 | COPY_PHASE_STRIP = NO 6 | IPHONEOS_DEPLOYMENT_TARGET = 12.0 7 | 8 | // Search Paths 9 | ALWAYS_SEARCH_USER_PATHS = NO 10 | 11 | // Signing 12 | CODE_SIGN_IDENTITY = iPhone Developer 13 | 14 | // Versioning 15 | VERSIONING_SYSTEM = apple-generic 16 | 17 | // Apple LLVM 9.0 - Code Generation 18 | GCC_DYNAMIC_NO_PIC = NO 19 | GCC_NO_COMMON_BLOCKS = YES 20 | 21 | // Apple LLVM 9.0 - Language 22 | GCC_C_LANGUAGE_STANDARD = gnu11 23 | 24 | // Apple LLVM 9.0 - Language - C++ 25 | CLANG_CXX_LANGUAGE_STANDARD = gnu++14 26 | CLANG_CXX_LIBRARY = libc++ 27 | 28 | // Apple LLVM 9.0 - Language - Modules 29 | CLANG_ENABLE_MODULES = YES 30 | 31 | // Apple LLVM 9.0 - Language - Objective C 32 | CLANG_ENABLE_OBJC_ARC = YES 33 | CLANG_ENABLE_OBJC_WEAK = YES 34 | 35 | // Apple LLVM 9.0 - Language - Preprocessing 36 | ENABLE_STRICT_OBJC_MSGSEND = YES 37 | 38 | // Apple LLVM 9.0 - Warnings - All languages 39 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES 40 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES 41 | CLANG_WARN_EMPTY_BODY = YES 42 | CLANG_WARN_BOOL_CONVERSION = YES 43 | CLANG_WARN_CONSTANT_CONVERSION = YES 44 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 45 | CLANG_WARN_ENUM_CONVERSION = YES 46 | CLANG_WARN_INT_CONVERSION = YES 47 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES 48 | CLANG_WARN_INFINITE_RECURSION = YES 49 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR 50 | CLANG_WARN_STRICT_PROTOTYPES = YES 51 | CLANG_WARN_COMMA = YES 52 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 53 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE 54 | CLANG_WARN_UNREACHABLE_CODE = YES 55 | GCC_WARN_UNUSED_FUNCTION = YES 56 | GCC_WARN_UNUSED_VARIABLE = YES 57 | 58 | // Apple LLVM 9.0 - Warnings - C++ 59 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES 60 | CLANG_WARN_SUSPICIOUS_MOVE = YES 61 | 62 | // Apple LLVM 9.0 - Warnings - Objective C 63 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR 64 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 65 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES 66 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES 67 | GCC_WARN_UNDECLARED_SELECTOR = YES 68 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR 69 | 70 | // Apple LLVM 9.0 - Warnings - Objective C and ARC 71 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 72 | 73 | // Static Analyzer - Generic Issuses 74 | CLANG_ANALYZER_NONNULL = YES 75 | 76 | // Static Analyzer - Issuses - Apple APIs 77 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE 78 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Builds/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Shared.xcconfig" 2 | 3 | // Build Options 4 | DEBUG_INFORMATION_FORMAT = dwarf-with-dsym 5 | VALIDATE_PRODUCT = YES 6 | 7 | // Apple LLVM 9.0 - Preprocessing 8 | ENABLE_NS_ASSERTIONS = NO 9 | 10 | // Swift Compiler - Code Generation 11 | SWIFT_COMPILATION_MODE = wholemodule 12 | SWIFT_OPTIMIZATION_LEVEL = -O 13 | 14 | // User-Defined 15 | MTL_ENABLE_DEBUG_INFO = NO 16 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Builds/ReleaseTest.xcconfig: -------------------------------------------------------------------------------- 1 | #include "SharedTest.xcconfig" 2 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Builds/Shared.xcconfig: -------------------------------------------------------------------------------- 1 | // Deployment 2 | INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks 3 | SKIP_INSTALL = YES 4 | APPLICATION_EXTENSION_API_ONLY = YES; 5 | 6 | // Linking 7 | DYLIB_COMPATIBILITY_VERSION = 1 8 | DYLIB_CURRENT_VERSION = 1 9 | DYLIB_INSTALL_NAME_BASE = @rpath 10 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks $(PROJECT_DIR)/../Carthage/Build/iOS 11 | 12 | // Search Paths 13 | FRAMEWORK_SEARCH_PATHS = $(inherited) $(PROJECT_DIR)/../Carthage/Build/iOS 14 | 15 | // Packing 16 | DEFINES_MODULE = YES 17 | INFOPLIST_FILE = Core/Configurations/Info.plist 18 | PRODUCT_BUNDLE_IDENTIFIER = com.example.iosproject.Core 19 | PRODUCT_NAME = $(TARGET_NAME:c99extidentifier) 20 | 21 | // Signing 22 | CODE_SIGN_IDENTITY = 23 | CODE_SIGN_STYLE = Automatic 24 | 25 | // User-Defined 26 | SWIFT_VERSION = 5.0 27 | TARGETED_DEVICE_FAMILY = 1,2 28 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Builds/SharedTest.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Shared.xcconfig" 2 | 3 | // Linking 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks 5 | 6 | // Packaging 7 | INFOPLIST_FILE = CoreTests/Configurations/Info.plist 8 | PRODUCT_BUNDLE_IDENTIFIER = com.example.iosproject.CoreTests 9 | PRODUCT_NAME = $(TARGET_NAME) 10 | 11 | // Build Options 12 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 13 | 14 | // Signing 15 | CODE_SIGN_STYLE = Automatic 16 | -------------------------------------------------------------------------------- /Core/Core/Configurations/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /Core/Core/Core.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | //! Project version number for Core. 4 | FOUNDATION_EXPORT double CoreVersionNumber; 5 | 6 | //! Project version string for Core. 7 | FOUNDATION_EXPORT const unsigned char CoreVersionString[]; 8 | 9 | // In this header, you should import all the public headers of your framework using statements like #import 10 | -------------------------------------------------------------------------------- /Core/Core/Core.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import UIKit 3 | 4 | public final class Core { 5 | public static let backgroundColor: UIColor = .red 6 | } 7 | -------------------------------------------------------------------------------- /Core/CoreTests/Configurations/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | -------------------------------------------------------------------------------- /Core/CoreTests/Tests/CoreTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Core 3 | 4 | class CoreTests: XCTestCase { 5 | 6 | override func setUp() { 7 | super.setUp() 8 | // Put setup code here. This method is called before the invocation of each test method in the class. 9 | } 10 | 11 | override func tearDown() { 12 | super.tearDown() 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | } 15 | 16 | func testExample() { 17 | // This is an example of a functional test case. 18 | // Use XCTAssert and related functions to verify your tests produce the correct results. 19 | } 20 | 21 | func testPerformanceExample() { 22 | // This is an example of a performance test case. 23 | self.measure { 24 | // Put the code you want to measure the time of here. 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Dangerfile: -------------------------------------------------------------------------------- 1 | # Warn about master branch 2 | warn("Please target PRs to `develop` branch") if github.branch_for_base != "master" 3 | 4 | # Sometimes it's a README fix, or something like that - which isn't relevant for 5 | # including in a project's CHANGELOG for example 6 | declared_trivial = github.pr_title.include? "#trivial" 7 | 8 | # Make it more obvious that a PR is a work in progress and shouldn't be merged yet 9 | warn("PR is classed as Work in Progress") if github.pr_title.include? "[WIP]" 10 | 11 | # Warn when there is a big PR 12 | warn("Big PR") if git.lines_of_code > 500 13 | 14 | ## changes in the project folder 15 | has_app_changes = !git.modified_files.grep(/iOSProject/).empty? 16 | 17 | # Changelog entries are required for changes to library files. 18 | no_changelog_entry = !git.modified_files.include?("CHANGELOG.yml") 19 | if has_app_changes && no_changelog_entry && !declared_trivial 20 | warn("Any meaningful changes to the project should be reflected in the Changelog. Please consider adding a note there.") 21 | end 22 | 23 | # Info.plist file shouldn't change often. Leave warning if it changes. 24 | is_plist_change = git.modified_files.include?("iOSProject/Configuration/Info.plist") 25 | 26 | if is_plist_change 27 | warn "Plist changed, don't forget to localize your plist values" 28 | end 29 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem 'danger', '~> 6.0.9' 4 | gem 'fastlane', '~> 2.131.0' 5 | gem 'travis', '~> 1.8.10' 6 | gem 'openssl', '~> 2.1.2' 7 | gem 'pry', '~> 0.12.2' 8 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.1) 5 | addressable (2.7.0) 6 | public_suffix (>= 2.0.2, < 5.0) 7 | atomos (0.1.3) 8 | babosa (1.0.2) 9 | backports (3.15.0) 10 | claide (1.0.3) 11 | claide-plugins (0.9.2) 12 | cork 13 | nap 14 | open4 (~> 1.3) 15 | coderay (1.1.2) 16 | colored (1.2) 17 | colored2 (3.1.2) 18 | commander-fastlane (4.4.6) 19 | highline (~> 1.7.2) 20 | connection_pool (2.2.2) 21 | cork (0.3.0) 22 | colored2 (~> 3.1) 23 | danger (6.0.9) 24 | claide (~> 1.0) 25 | claide-plugins (>= 0.9.2) 26 | colored2 (~> 3.1) 27 | cork (~> 0.1) 28 | faraday (~> 0.9) 29 | faraday-http-cache (~> 2.0) 30 | git (~> 1.5) 31 | kramdown (~> 2.0) 32 | kramdown-parser-gfm (~> 1.0) 33 | no_proxy_fix 34 | octokit (~> 4.7) 35 | terminal-table (~> 1) 36 | declarative (0.0.10) 37 | declarative-option (0.1.0) 38 | digest-crc (0.4.1) 39 | domain_name (0.5.20190701) 40 | unf (>= 0.0.5, < 1.0.0) 41 | dotenv (2.7.5) 42 | emoji_regex (1.0.1) 43 | ethon (0.12.0) 44 | ffi (>= 1.3.0) 45 | excon (0.66.0) 46 | faraday (0.15.4) 47 | multipart-post (>= 1.2, < 3) 48 | faraday-cookie_jar (0.0.6) 49 | faraday (>= 0.7.4) 50 | http-cookie (~> 1.0.0) 51 | faraday-http-cache (2.0.0) 52 | faraday (~> 0.8) 53 | faraday_middleware (0.13.1) 54 | faraday (>= 0.7.4, < 1.0) 55 | fastimage (2.1.7) 56 | fastlane (2.131.0) 57 | CFPropertyList (>= 2.3, < 4.0.0) 58 | addressable (>= 2.3, < 3.0.0) 59 | babosa (>= 1.0.2, < 2.0.0) 60 | bundler (>= 1.12.0, < 3.0.0) 61 | colored 62 | commander-fastlane (>= 4.4.6, < 5.0.0) 63 | dotenv (>= 2.1.1, < 3.0.0) 64 | emoji_regex (>= 0.1, < 2.0) 65 | excon (>= 0.45.0, < 1.0.0) 66 | faraday (~> 0.9) 67 | faraday-cookie_jar (~> 0.0.6) 68 | faraday_middleware (~> 0.9) 69 | fastimage (>= 2.1.0, < 3.0.0) 70 | gh_inspector (>= 1.1.2, < 2.0.0) 71 | google-api-client (>= 0.21.2, < 0.24.0) 72 | google-cloud-storage (>= 1.15.0, < 2.0.0) 73 | highline (>= 1.7.2, < 2.0.0) 74 | json (< 3.0.0) 75 | jwt (~> 2.1.0) 76 | mini_magick (>= 4.9.4, < 5.0.0) 77 | multi_xml (~> 0.5) 78 | multipart-post (~> 2.0.0) 79 | plist (>= 3.1.0, < 4.0.0) 80 | public_suffix (~> 2.0.0) 81 | rubyzip (>= 1.2.2, < 2.0.0) 82 | security (= 0.1.3) 83 | simctl (~> 1.6.3) 84 | slack-notifier (>= 2.0.0, < 3.0.0) 85 | terminal-notifier (>= 2.0.0, < 3.0.0) 86 | terminal-table (>= 1.4.5, < 2.0.0) 87 | tty-screen (>= 0.6.3, < 1.0.0) 88 | tty-spinner (>= 0.8.0, < 1.0.0) 89 | word_wrap (~> 1.0.0) 90 | xcodeproj (>= 1.8.1, < 2.0.0) 91 | xcpretty (~> 0.3.0) 92 | xcpretty-travis-formatter (>= 0.0.3) 93 | ffi (1.11.1) 94 | gh (0.14.0) 95 | addressable 96 | backports 97 | faraday (~> 0.8) 98 | multi_json (~> 1.0) 99 | net-http-persistent (>= 2.7) 100 | net-http-pipeline 101 | gh_inspector (1.1.3) 102 | git (1.5.0) 103 | google-api-client (0.23.9) 104 | addressable (~> 2.5, >= 2.5.1) 105 | googleauth (>= 0.5, < 0.7.0) 106 | httpclient (>= 2.8.1, < 3.0) 107 | mime-types (~> 3.0) 108 | representable (~> 3.0) 109 | retriable (>= 2.0, < 4.0) 110 | signet (~> 0.9) 111 | google-cloud-core (1.3.1) 112 | google-cloud-env (~> 1.0) 113 | google-cloud-env (1.2.1) 114 | faraday (~> 0.11) 115 | google-cloud-storage (1.16.0) 116 | digest-crc (~> 0.4) 117 | google-api-client (~> 0.23) 118 | google-cloud-core (~> 1.2) 119 | googleauth (>= 0.6.2, < 0.10.0) 120 | googleauth (0.6.7) 121 | faraday (~> 0.12) 122 | jwt (>= 1.4, < 3.0) 123 | memoist (~> 0.16) 124 | multi_json (~> 1.11) 125 | os (>= 0.9, < 2.0) 126 | signet (~> 0.7) 127 | highline (1.7.10) 128 | http-cookie (1.0.3) 129 | domain_name (~> 0.5) 130 | httpclient (2.8.3) 131 | json (2.2.0) 132 | jwt (2.1.0) 133 | kramdown (2.1.0) 134 | kramdown-parser-gfm (1.1.0) 135 | kramdown (~> 2.0) 136 | launchy (2.4.3) 137 | addressable (~> 2.3) 138 | memoist (0.16.0) 139 | method_source (0.9.2) 140 | mime-types (3.3) 141 | mime-types-data (~> 3.2015) 142 | mime-types-data (3.2019.0904) 143 | mini_magick (4.9.5) 144 | multi_json (1.13.1) 145 | multi_xml (0.6.0) 146 | multipart-post (2.0.0) 147 | nanaimo (0.2.6) 148 | nap (1.1.0) 149 | naturally (2.2.0) 150 | net-http-persistent (3.1.0) 151 | connection_pool (~> 2.2) 152 | net-http-pipeline (1.0.1) 153 | no_proxy_fix (0.1.2) 154 | octokit (4.14.0) 155 | sawyer (~> 0.8.0, >= 0.5.3) 156 | open4 (1.3.4) 157 | openssl (2.1.2) 158 | os (1.0.1) 159 | plist (3.5.0) 160 | pry (0.12.2) 161 | coderay (~> 1.1.0) 162 | method_source (~> 0.9.0) 163 | public_suffix (2.0.5) 164 | pusher-client (0.6.2) 165 | json 166 | websocket (~> 1.0) 167 | representable (3.0.4) 168 | declarative (< 0.1.0) 169 | declarative-option (< 0.2.0) 170 | uber (< 0.2.0) 171 | retriable (3.1.2) 172 | rouge (2.0.7) 173 | rubyzip (1.2.4) 174 | sawyer (0.8.2) 175 | addressable (>= 2.3.5) 176 | faraday (> 0.8, < 2.0) 177 | security (0.1.3) 178 | signet (0.11.0) 179 | addressable (~> 2.3) 180 | faraday (~> 0.9) 181 | jwt (>= 1.5, < 3.0) 182 | multi_json (~> 1.10) 183 | simctl (1.6.5) 184 | CFPropertyList 185 | naturally 186 | slack-notifier (2.3.2) 187 | terminal-notifier (2.0.0) 188 | terminal-table (1.8.0) 189 | unicode-display_width (~> 1.1, >= 1.1.1) 190 | travis (1.8.10) 191 | backports 192 | faraday (~> 0.9) 193 | faraday_middleware (~> 0.9, >= 0.9.1) 194 | gh (~> 0.13) 195 | highline (~> 1.6) 196 | launchy (~> 2.1) 197 | pusher-client (~> 0.4) 198 | typhoeus (~> 0.6, >= 0.6.8) 199 | tty-cursor (0.7.0) 200 | tty-screen (0.7.0) 201 | tty-spinner (0.9.1) 202 | tty-cursor (~> 0.7) 203 | typhoeus (0.8.0) 204 | ethon (>= 0.8.0) 205 | uber (0.1.0) 206 | unf (0.1.4) 207 | unf_ext 208 | unf_ext (0.0.7.6) 209 | unicode-display_width (1.6.0) 210 | websocket (1.2.8) 211 | word_wrap (1.0.0) 212 | xcodeproj (1.12.0) 213 | CFPropertyList (>= 2.3.3, < 4.0) 214 | atomos (~> 0.1.3) 215 | claide (>= 1.0.2, < 2.0) 216 | colored2 (~> 3.1) 217 | nanaimo (~> 0.2.6) 218 | xcpretty (0.3.0) 219 | rouge (~> 2.0.7) 220 | xcpretty-travis-formatter (1.0.0) 221 | xcpretty (~> 0.2, >= 0.0.7) 222 | 223 | PLATFORMS 224 | ruby 225 | 226 | DEPENDENCIES 227 | danger (~> 6.0.9) 228 | fastlane (~> 2.131.0) 229 | openssl (~> 2.1.2) 230 | pry (~> 0.12.2) 231 | travis (~> 1.8.10) 232 | 233 | BUNDLED WITH 234 | 1.17.2 235 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 messeb (https://github.com/messeb) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | RUBY := $(shell command -v ruby 2>/dev/null) 2 | HOMEBREW := $(shell command -v brew 2>/dev/null) 3 | BUNDLER := $(shell command -v bundle 2>/dev/null) 4 | 5 | default: setup 6 | 7 | setup: \ 8 | pre_setup \ 9 | check_for_ruby \ 10 | check_for_homebrew \ 11 | update_homebrew \ 12 | install_carthage \ 13 | install_bundler_gem \ 14 | install_ruby_gems \ 15 | install_carthage_dependencies 16 | 17 | pull_request: \ 18 | test \ 19 | codecov_upload \ 20 | danger 21 | 22 | pre_setup: 23 | $(info iOS project setup ...) 24 | 25 | check_for_ruby: 26 | $(info Checking for Ruby ...) 27 | 28 | ifeq ($(RUBY),) 29 | $(error Ruby is not installed) 30 | endif 31 | 32 | check_for_homebrew: 33 | $(info Checking for Homebrew ...) 34 | 35 | ifeq ($(HOMEBREW),) 36 | $(error Homebrew is not installed) 37 | endif 38 | 39 | update_homebrew: 40 | $(info Update Homebrew ...) 41 | 42 | brew update 43 | 44 | install_swift_lint: 45 | $(info Install swiftlint ...) 46 | 47 | brew unlink swiftlint || true 48 | brew install swiftlint 49 | brew link --overwrite swiftlint 50 | 51 | install_bundler_gem: 52 | $(info Checking and install bundler ...) 53 | 54 | ifeq ($(BUNDLER),) 55 | gem install bundler -v '~> 2.0' 56 | else 57 | gem update bundler '~> 2.0' 58 | endif 59 | 60 | install_ruby_gems: 61 | $(info Install Ruby Gems ...) 62 | 63 | bundle install 64 | 65 | install_carthage: 66 | $(info Install Carthage ...) 67 | 68 | brew unlink carthage || true 69 | brew install carthage 70 | brew link --overwrite carthage 71 | 72 | install_carthage_dependencies: 73 | $(info Install Carthage Dependencies ...) 74 | 75 | carthage bootstrap --platform ios --cache-builds 76 | 77 | codecov_upload: 78 | curl -s https://codecov.io/bash | bash 79 | 80 | danger: 81 | bundle exec danger 82 | 83 | test: 84 | bundle exec fastlane test 85 | 86 | staging: 87 | bundle exec fastlane test # staging 88 | 89 | release: 90 | bundle exec fastlane test # release 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # iOS project template 2 | 3 |

4 | 5 |

6 | 7 | This repository contains a template for iOS projects with a framework-oriented architecture approach, preconfigured [fastlane](https://fastlane.tools) lanes, [Travis CI](https://travis-ci.com) jobs and Github integrations of [Codecov](https://codecov.io), [HoundCI](https://houndci.com) for [SwiftLint](https://github.com/realm/SwiftLint) and [Danger](https://danger.systems/ruby). It provides a starting point for new projects which can be immediately distributed via HockeyApp and Testflight. 8 | 9 | This template has three goals: 10 | 11 | * It can easily be configured. 12 | * It will contain all the necessary files to build and distribute the app. 13 | * The different parts work independently. 14 | 15 | [![Build Status](https://travis-ci.org/messeb/ios-project-template.svg?branch=master)](https://travis-ci.org/messeb/ios-project-template) 16 | 17 | #### Contact 18 | 19 |
20 | Follow me on Twitter: [@_messeb](https://to.messeb.com/twitter) 21 | 22 |
23 | Contact me on LinkedIn: [@messingfeld](https://to.messeb.com/contact) 24 | 25 | --- 26 | #### Table of Contents 27 | 28 | * [Introduction](#introduction) 29 | * [Xcode Project](#xcode-project) 30 | * [Project structure](#project-structure) 31 | * [Configurations (*.xcconfig files)](#configurations-xcconfig-files) 32 | * [Project frameworks](#project-frameworks) 33 | * [Build & sign the app](#build--sign-the-app) 34 | * [Used fastlane features](#used-fastlane-features) 35 | * [Code signing with fastlane](#code-signing-with-fastlane) 36 | * [Fastlane lanes](#fastlane-lanes) 37 | * [Build Server](#build-server) 38 | * [Travis CI](#travis-ci) 39 | * [Environment variables](#environment-variables) 40 | * [Distribution](#distribution) 41 | * [HockeyApp](#hockeyapp) 42 | * [Testflight & App Store](#testflight--app-store) 43 | * [GitHub Integrations](#github-integrations) 44 | * [Danger](#danger) 45 | * [HoundCI](#houndci) 46 | * [Codecov](#codecov) 47 | * [Usage](#usage) 48 | --- 49 | 50 | ## Introduction 51 | 52 | To set up new iOS projects with a ci/cd pipeline is always a little mess. Everyone gives input, but usually, someone of the team members has to care about all the following steps: 53 | 54 | * Setup a build server or build service. 55 | * Manage the internal distribution of the app to the product owner and testers. 56 | * Providing the signing certificates and provisioning profiles. 57 | * Configure signing for different release stages. 58 | * Creating ci/cd pipelines for pull request and distribution. 59 | * Add code quality definitions for pull requests, like linting and test coverage rules. 60 | 61 | The repository contains an example solutions for all of the points. For every step, it includes one solution. 62 | 63 | ## Xcode Project 64 | 65 | The iOS template consists of an Xcode workspace file ([iOSProject.xcworkspace](./iOSProject.xcworkspace)) with the project for the app ([iOSProject.xcodeproj](./iOSProject.xcodeproj)) and a framework project ([Core.xcodeproj](./Core/Core.xcodeproj)), named _Core_. The structure is: 66 | 67 | ![xcode-project-structure](./documentation/images/xcode-project-structure.png) 68 | 69 | ### Project structure 70 | 71 | The app project is separated into three main folders: _Scenes_, _Resources_, and _Configurations_. It's only an alternative structure to the default Xcode project. 72 | 73 | **Scenes**: Should be the folder, where the different scenes or modules of the app are placed. The concrete structure depends on the chosen app architecture. 74 | 75 | **Resources**: Contains all assets for the app, like the launch screen or the image assets. 76 | 77 | **Configurations**: Contains all the files which define the build artifacts of the app. It contains the [Info.plist](./iOSProject/Configurations/Info.plist) and a [Builds](./iOSProject/Configurations/Builds) folder with _*.xcconfig_ files for the different build configurations. 78 | 79 | The root folder of the project also includes the [AppDelegate.swift](./iOSProject/AppDelegate.swift) and the [main.swift](./iOSProject/main.swift) files. 80 | 81 | **AppDelegate.swift**: In the AppDelegate the main `UIWindow` instance of the app is created, and an empty `UIViewController` instance is assigned as the root view controller. Modern app architectures, like _MVVM_ or _VIPER_, work better with manual creation of the entry point, than using the `Main Interface` possibility. Therefore the `Main.storyboard` file was deleted and the `Main Interface` reference from the project removed: 82 | 83 | ![xcode-main-interface-reference.png](./documentation/images/xcode-main-interface-reference.png) 84 | 85 | **main.swift**: In a default iOS project, the `AppDelegate` class is annotated with [@UIApplicationMain](https://docs.swift.org/swift-book/ReferenceManual/Attributes.html) (scroll down to _UIApplicationMain_). It replaces the `main` function of the project and the manual call of [UIApplicationMain(_:_:_:_:)](https://developer.apple.com/documentation/uikit/1622933-uiapplicationmain). To reenable the possibility to call it manual, the annotation has to be removed, and you have to create a [main.swift](./iOSProject/main.swift) file. With a [main.swift](./iOSProject/main.swift) file, it's possible to customize the parameter for the [UIApplicationDelegate](https://developer.apple.com/documentation/uikit/uiapplicationdelegate). You can set an empty instance for unit tests to prevent side effects of parallel code execution in the test host. 86 | 87 | #### Configurations (\*.xcconfig files) 88 | 89 | The whole project configurations are moved from the project file to _*.xcconfig_ files in the [`iOSProject/Configurations/Builds`](./iOSProject/Configurations/Builds) folder. 90 | The usage of _*.xcconfig_ files in a project solves two problems: 91 | 92 | * Separation of project configuration and file references in the project. Now, only changes of files and folders are made in the project file. Changes of configurations in the project file should always be rejected. This prevents mistaken changes during development. 93 | * Traceability which changes are done in the project configuration during development. The history of changes in a decides _*.xcconfig_ file can be more straightforward analyze, than in a complex project file with additional modifications. 94 | 95 | You see in the project build settings that all the configurations are moved from the project to config files. Enable _All_ and _Levels_: 96 | 97 | ![xcode-build-settings-xcconfig.png](./documentation/images/xcode-build-settings-xcconfig.png) 98 | 99 | The configurations are also split in different files: 100 | 101 | ![xcode-xcconfig-files.png](./documentation/images/xcode-xcconfig-files.png) 102 | 103 | **Application.xcconfig**: Contains all configurations which were in the _Project_ section of the build settings. These values are set for all of the targets of the project, _iOSProject_ and _iOSProjectTests_. 104 | 105 | **Debug.xcconfig**, **Staging.xcconfig**, **Release.xcconfig**: Contains the different configuration values for the various app builds variants of the _iOSProject_ target. The target has configured for three app builds, for varying stages and with different bundle identifiers. Same configuration values are extracted to **Shared.xcconfig**. For the test target exists the equivalent **\*Test.xcconfig** files. 106 | 107 | **DebugSigning.xcconfig**, **StagingSigning.xcconfig**, **ReleaseSigning.xcconfig**: Contains the configurations for creating the different build artifacts of the _iOSProject_ target. Like the bundle identifiers or if you want _Manual Code Signing_. 108 | 109 | #### Target configurations 110 | 111 | The _*.xcconfig_ files can assign to project configurations: 112 | 113 | ![xcode-project-configuration.png](./documentation/images/xcode-project-configuration.png) 114 | 115 | With the different configurations, _Debug_, _Staging_ and _Release_, you can produce different app artifacts. The app artifacts can distinguish by bundle identifier, display name and signing, because if the different _*.xcconfig_ files. 116 | 117 | **Debug**: Can be used for development. It has an own bundle identifier, the code signing is set to _Automatically_, and the _Team_ could be set to an (enterprise) developer team account, to which all the developers belong. So, Xcode manages the code signing, and every developer can test the app directly on a real device. 118 | 119 | **Staging**: Can be used for In-House-Testing. With an own bundle identifier and signing information, it can be distributed via an external service, like HockeyApp. If you sign your staging app artifacts for an enterprise release, every member of your company or your client could test the app without submitting to Testflight. 120 | 121 | **Release**: Should produce the app artifacts for the Testflight beta test and the App Store release. It also has it's own bundle identifier and signing configuration. 122 | 123 | The whole management of the different app artifacts is done inside the Xcode project, because this maintains the independence from third-party configurations steps, like in [fastlane](https://fastlane.tools/). Switching between different build methods is straightforward. You can build and export the app artifacts via Xcode or use `xcodebuild` on the command line, or yet use [fastlane](https://fastlane.tools/). With the extracted signing configurations in the _*.Signing.xcconfig_ files, it's also simple to modify the different app artifacts settings. 124 | 125 | ### Project frameworks 126 | 127 | The project workspace also contains a `Core` framework. It's a sample integration of a custom framework mainly for separate different code parts in different modules. 128 | Dedicated frameworks for different logical components in the app have some advantages: 129 | 130 | * The separated code in frameworks makes it easier to manage the whole code basis. If you have additional targets, like for a Today Extension, you only need to import the relevant modules in it and keep the target artifacts smaller. And you don't have to hassle with the _Target Membership_ of the source code files. Keep in mind to enable the _App Extension_ option _Allow app extension API only_ in the project settings of the frameworks to prevent using unsupported features for extensions. 131 | * Because only public members of classes in frameworks are accessible from outside, you usually care more about the public interface. That's a small part of creating cleaner code, but it helps you a lot if you can improve the implementation of features over time and don't have to worry that someone uses modules in an not intended way. 132 | * The frameworks are separated projects of the project workspace and have an own project file. If you add files to the framework, these only effects the framework project file. That makes commits and merges much more comfortable, than handling the whole file references in one project file. 133 | * Framework projects in one workspace make Swift code migration easier to handle, because you migrate your whole project in one step, and not each framework for its own. 134 | * The usage of frameworks affects the build time positive during development, too. Frameworks will only rebuild if you made changes in it. 135 | 136 | #### Project frameworks vs. Carthage / Cocoapods 137 | 138 | An alternative to the framework projects in the workspace, you could use _Carthage_ or _Cocoapods_ to build submodules for the project and include them into it. But I decide against that solution, because: 139 | 140 | * The development with frameworks in a workspace is much faster and direct than via a dependency management system. You can develop in the same Xcode window, and changes in the framework will directly affect the other parts of the code base. You don't have to run an additional step or change paths for development. 141 | * The frameworks are dedicated to using these at first only in this one app. You don't need some extra release step or specific versioning. Changes in one framework are changes in the app. Of course, the framework could extract later in an own _Carthage_ / _Cocoapods_ project, if it grows to an own project - and then you will lose your git history. 142 | 143 | #### Integration in project 144 | 145 | To integrate a framework in your app project, just add it to the **Embedded Binaries** section of your project target: 146 | 147 | ![](./documentation/images/xcode-embedded-binaries.png) 148 | 149 | 150 | ### Third-party dependencies 151 | 152 | The project template uses [Carthage](https://github.com/Carthage/Carthage) as dependency manager. Just follow the instructions in the [Adding frameworks to an application](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to use the dependencies in your app. 153 | 154 | If you want to use the Carthage dependencies in one of the project frameworks, you have to add the frameworks also in the app target ([Adding frameworks to an application](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application)). Also, you have to link the Carthage frameworks to your framework: 155 | 156 | ![](./documentation/images/xcode-framework-carthage-linking.png) 157 | 158 | 159 | 160 | Also, you have to add the Carthage folder (relative path from framework: `$(PROJECT_DIR)/../Carthage/Build/iOS`) to the environment variables `LD_RUNPATH_SEARCH_PATHS` and `FRAMEWORK_SEARCH_PATHS`. Have a look at the [Shared.xcconfig](Core/Core/Configurations/Builds/Shared.xcconfig) file of the framework. 161 | 162 | ## Build & sign the app 163 | 164 | To build and sign an app artifact the template uses [fastlane](https://www.fastlane.tools). Fastlane provides an extensive collection of Ruby scripts to support the daily routines of iOS developer. The most used functionality is probably the abstraction for the command line tool `xcodebuild` with the Ruby functions [`run_tests`](https://docs.fastlane.tools/actions/run_tests/) and [`build_ios_app`](https://docs.fastlane.tools/actions/build_ios_app/). Fastlane also delivers fast and regular updates for changes of the abstracted functionality. Perhaps you don't even recognize that the command line arguments of `xcodebuild` changed over time if you kept fastlane up to date. The abstraction and the proper maintenance are only two strengths of fastlane which makes it worth to use it. 165 | 166 | ### Used fastlane features 167 | 168 | The project template divides responsibilities for the build and distribution process to the Xcode project and the fastlane scripts. 169 | 170 | The variant configuration of the different build artifacts is done via the _Debug_, _Staging_ and _Release_ configuration in the Xcode project. Also, the used signing settings are configured in the different `*.xcconfig` files. These configurations could also be done via fastlane using functions like [update\_app\_identifier](https://docs.fastlane.tools/actions/update_app_identifier/) or the use the [Appfile](https://docs.fastlane.tools/advanced/Appfile/). But if you do that configuration with fastlane, you always need it. With the base configuration already defined in the project, you could build your variants directly with Xcode - if you have installed the signing certificate and the mobile provisioning profile. 171 | 172 | To build the different app configuration on a build server fastlane is used. Fastlane is also responsible for the creation of the signing environment and the distribution via [HockeyApp](https://www.hockeyapp.net/) and [Testflight](https://developer.apple.com/testflight/). The alternative is to create scripts in other languages or do it manually. So if you want to switch from fastlane to another solution, you only have to care about these steps. 173 | 174 | These are the aberrations in a project. You have to decide on which step you want to use which tool. There is IMHO no right or wrong way, only personal preferences. 175 | 176 | ### Code signing with fastlane 177 | 178 | Fastlane also offers excellent solutions for code signing with [match](https://docs.fastlane.tools/actions/match/) or [cert](https://docs.fastlane.tools/actions/cert/) and [sigh](https://docs.fastlane.tools/actions/sigh/), but I choose another way to create a signing environment. Instead, that fastlane creates and organizes the certificate and provisioning profiles, I want to create them manually. It's often an use case that these files cannot be generated automatically or managed by fastlane, because different parties with different development setups in the company should work with them, like in-house developer and external IT project houses. 179 | 180 | My solution, inspired by [Travis CI for iOS from objc.io](https://www.objc.io/issues/6-build-tools/travis-ci/), is that the certificates and mobile provisioning profiles are saved encrypted in the git repository. And for each distribution configuration (Staging, Release) a pair of them are saved: 181 | 182 | **Staging**: In [signing/staging](./signing/staging) could be kept a certificate for enterprise distribution with the corresponding provisioning profile for ad-hoc or in-house distribution. 183 | 184 | **Release**: [signing/release](./signing/release) should contain the certificate and mobile provisioning profile for the app store release. 185 | 186 | To create a signing environment with pre-shipped certificates and mobile provisioning profiles, you have to care about the following steps. 187 | 188 | * Decrypt the certificates and provisioning profiles. 189 | * Create and configure a keychain for the certificate. From my experience, the created keychain should set as default keychain, added to the search list (then it's also displayed in the _Keychain Access_) and be unlocked. 190 | * Import the certificate to the created keychain. 191 | * Copy the mobile provisioning profile to `/Library/MobileDevice/Provisioning Profiles/` 192 | 193 | After a build, you should clean up your signing environment. Especially if it's shared build server. Do the following steps: 194 | 195 | * Delete the created keychain. 196 | * Delete the provisioning profiles, which were copied to `/Library/MobileDevice/Provisioning Profiles/`. 197 | * Delete the unencrypted certificates and mobile provisioning profiles. 198 | 199 | I created some ruby methods in [fastlane/libs/signing.rb](fastlane/libs/signing.rb), which use built-in fastlane functions like [create_keychain](https://docs.fastlane.tools/actions/create_keychain/), [unlock_keychain](https://docs.fastlane.tools/actions/unlock_keychain/) and [import_file from KeychainImporter](https://github.com/fastlane/fastlane/blob/master/fastlane_core/lib/fastlane_core/keychain_importer.rb) to create and delete the signing environment. In the fastlane lane you can directly use it with `create_signing_configuration` and `clear_signing_configuration`. 200 | To encrypt and decrypt the certificates and mobile provisioning profile the template uses the [OpenSSL::Cipher::AES256](https://ruby-doc.org/stdlib-2.5.1/libdoc/openssl/rdoc/OpenSSL/Cipher.html) symmetric algorithm. The implementation is in [fastlane/libs/encryption.rb](fastlane/libs/encryption.rb). 201 | 202 | To create the appropriate signing environment, with the right certificate and mobile provisioning profile, the appropriate folder is referenced in the fastlane lane. 203 | 204 | ### Fastlane lanes 205 | 206 | The [Fastfile](fastlane/Fastfile) contains only two type of lanes. 207 | One self-explanatory lane for executing the unit tests: 208 | 209 | ``` 210 | lane :test do 211 | run_tests(scheme: 'iOSProject') 212 | end 213 | ``` 214 | 215 | And the lanes for building an app artifact, like for the App Store build: 216 | 217 | ``` 218 | lane :release do 219 | build("../signing/release", "Release" ,"app-store") 220 | upload_to_testflight(skip_submission: true) 221 | end 222 | ``` 223 | 224 | The `build` method is an abstraction to combine the creating / deletion of the signing environment and compile the app. It's calling the created methods from [fastlane/libs/signing.rb](fastlane/libs/signing.rb) and the fastlane function [build\_ios\_app](https://docs.fastlane.tools/actions/build_ios_app/). Because of the `*.xcconfig` configurations in the Xcode project the right certificate and profile are chosen during the build. For the _Staging_ build its [StagingSigning.xcconfig](iOSProject/Configurations/Builds/Signing/StagingSigning.xcconfig), and for the _Release_ build its [ReleaseSigning.xcconfig](iOSProject/Configurations/Builds/Signing/ReleaseSigning.xcconfig). 225 | 226 | The lanes will be executed in the [Makefile](./Makefile) targets `test`, `staging` and `release` in the build jobs. 227 | 228 | ## Build server 229 | 230 | Nobody really likes to set up and manage a macOS build server. In comparison to other build setups for backend services or even Android apps, you need real hardware or an individual plan of a cloud build service. If you manage your build server on your own, you also have to care about the installed Xcode versions and required project dependencies. 231 | 232 | To minimize the manual and predefined setup of your build environment, I provide already a solution with my GitHub project [Setup your iOS project environment with a Shellscript, Makefile or Rakefile](https://to.messeb.com/2w3obUl). It shows you a way how your build server only needs Xcode and Ruby preinstalled. All other dependencies can come with the iOS project. Also, this is the base for this project template. 233 | 234 | ### Travis CI 235 | 236 | This template uses [Travis CI](https://travis-ci.com/) as build service. Travis CI provides via the [.travis.yml](.travis.yml) file an easy way to configure the build environment for an iOS build. Simple set the `language` value to _objective-c_ and the `osx_image` to the value of the required Xcode version, e.g. _xcode10_. More info are in the [Building an Objective-C or Swift Project](https://docs.travis-ci.com/user/languages/objective-c/) section of the documentation. 237 | 238 | 239 | To minimize the individual configuration setup for the chosen build service, you should have all required setup steps capsulated in a script, like a [Makefile](./Makefile). The [Makefile](./Makefile) in this project template contains two major parts. It has one `setup` target, which installs all the dependencies for the iOS build. The second part are the build targets: `pull_request`, `staging` & `release` 240 | 241 | * `pull_request`: It checks the linting against the SwiftLint rules ([.swiftlint.yml](.swiftlint.yml)) with the [HoundCI](https://houndci.com/) service ([.hound.yml](.hound.yml)), runs the unit test with [fastlane](https://fastlane.tools/) ([Fastfile #test](./fastlane/Fastfile)), uploads the code coverage of the unit tests to [Codecov](https://codecov.io/) ([.codecov.yml](.codecov.yml)) and checks the pull request with [Danger](https://danger.systems/) ([Dangerfile](./Dangerfile)). The results of the different services and script are combined in the Github pull request. 242 | 243 | The reason why all the steps are different Makefile targets is, that it depends on your build server and your git hosting provider, how the steps are executed. E.g., HoundCI works as a GitHub integration and is automatically performed on an updated pull request. So you may have to change the scripts to work with your build server setup, or even change the used service if you are not using GitHub. It's much easier to maintain these small subtasks than one long script. 244 | 245 | * `staging`: This target executes the fastlane lane _staging_. It will create an *ad-hoc*-signed build and uploads it to [HockeyApp](http://www.hockeyapp.net) 246 | 247 | * `release`: This target executes the fastlane lane _release_. It will create an *appstore*-signed build and uploads it to [App Store Connect](https://appstoreconnect.apple.com) 248 | 249 | #### Configure build jobs 250 | 251 | Travis CI uses the [.travis.yml](.travis.yml) file as configuration for the build jobs. Based on the actions in a git repository, it will execute different jobs. In this project template, there are three build jobs defined: *Pull Request*, *Staging*, *Release*. These should be run on different actions: 252 | 253 | * *Pull Request*: This job should be executed if a pull request was created or updated. It calls the Makefile target `pull_request`. 254 | 255 | * *Staging*: This job should be executed if a commit or merge was made on the master branch. It calls the Makefile target `staging`. 256 | 257 | * *Release*: This job should be executed if a new tag was created. It calls the Makefile target `release`. 258 | 259 | This rules can be defined with the [Build Stages](https://docs.travis-ci.com/user/build-stages). The project has only one `build` stage because the [Makefile](./Makefile) targets do the whole work and the project should not depend on a particular build service. 260 | With the `if` conditions its possible to define which job should be executed. E.g., the *Pull Request* will be only executed, if you are on a pull request: 261 | 262 | ``` 263 | jobs: 264 | include: 265 | - name: Pull Request 266 | if: type = pull_request 267 | stage: build 268 | script: make pull_request 269 | ``` 270 | 271 | More pieces of information for conditional builds are in the [https://docs.travis-ci.com/user/conditional-builds-stages-jobs/](https://docs.travis-ci.com/user/conditional-builds-stages-jobs/) section of Travis CI. 272 | 273 | The [.travis.yml](.travis.yml) syntax also has elements for installing the required dependencies ([Installing Dependencies](https://docs.travis-ci.com/user/installing-dependencies/)) before executing the build steps. You can also override the installation step for the dependencies and provide a custom script. 274 | An overwrite will prevent the project interpretation of Travis CI. It would automatically install dependencies because it would run `bundle install` or `cocoapods install` if it finds a `Gemfile` or `Podfile` file. First of all, this sounds great, but this works only on Travis CI, and you should be build service independent. 275 | So, just the Makefile target `setup` will execute and installs all the required dependencies: 276 | 277 | ``` 278 | install: make setup 279 | ``` 280 | 281 | #### Configure the build service 282 | 283 | Except for Travis CI, there are a lot of other iOS build services, like Circle CI or bitrise. Each of the services has its own strengths and weaknesses. So, you should look more often in the logs of the used services, if something could work better. 284 | If you use *Carthage*, like in the project template, you will face the missing caching of the *Carthage* frameworks. So each build takes longer than it's necessary. But you can configure folders, which should be cached between different builds. Have a look at the documentation ([Caching Dependencies and Directories](https://docs.travis-ci.com/user/caching/)). 285 | 286 | For the iOS project template its good to cache the selected Ruby version, the Ruby Gems, the Homebrew packages, and the Carthage folder: 287 | 288 | ``` 289 | cache: 290 | bundler: true 291 | directories: 292 | - $HOME/.rvm/ 293 | - $HOME/Library/Caches/Homebrew 294 | - $TRAVIS_BUILD_DIR/Carthage 295 | ``` 296 | 297 | On other build services, you will face other challenges. So keep in 298 | 299 | #### Connect Travis CI to the GitHub repository 300 | 301 | To connect your Github repository to the Travis CI build service, you have to visit [https://travis-ci.com](https://travis-ci.com). 302 | You will log in with a Github Account and then connect one or more repos with Travis CI: 303 | 304 | ![Travis CI Repository Selection](./documentation/images/travis-ci-repository-selection.png) 305 | 306 | ### Environment variables 307 | 308 | The whole ci/cd pipeline needs credentials for some steps. These should not be publicly available for everyone, even not for every developer. Only the build server should have access to them. 309 | The project needs the following environment variables: 310 | 311 | **FILE_DECRYPTION_KEY**: The decryption key for the encrypted certificates and provisioning profiles in [./signing](signing). 312 | 313 | **FASTLANE_USER**: Email address of an App Store Connect user to upload an _*.ipa_ to App Store Connect. 314 | 315 | **FASTLANE_FASTLANE_PASSWORD**: Password of `FASTLANE_USER`. 316 | 317 | **FASTLANE_DONT_STORE_PASSWORD**: Flag, that the user credentials should not save in the local keychain of the build server. Should always be 1. 318 | 319 | **HOCKEYAPP_API_TOKEN**: API token to upload an _*.ipa_ to HockeyApp. 320 | 321 | **CODECOV_TOKEN**: Codecov token for the connection to the Codecov project. 322 | 323 | **DANGER_GITHUB_API_TOKEN** Personal access token of a GitHub Bot User account. With this one, the pull request comments will be made. 324 | 325 | **GITHUB_ACCESS_TOKEN** Personal access token of a GitHub account, to not run in rate limits for anonymous user. These will happen for fetching pre-build Carthage frameworks. 326 | 327 | In Travis CI you can set the environment variables in the _Settings_ of a project. These will be automatically injected into every new build. 328 | 329 | ![travis-ci-environment-variables](./documentation/images/travis-ci-environment-variables.png) 330 | 331 | ## Distribution 332 | 333 | During the development of an app, there are different requirements for the distribution of an app. After you implemented a feature, at first the QA department and the product owner should test it. And only after approval, the version should be distributed to the internal tester. 334 | Then it should go to a public beta and the App Store release. 335 | 336 | To give the QA department and the product owner access to a pre-release app version, the app usually signed as Ad-hoc or In-House build. Instead of sending the _*.ipa_ through email or other ways, Apple supports distributing these versions over an own web server: [Distribute in-house apps from a web server](https://help.apple.com/deployment/ios/#/apda0e3426d7). 337 | Keep in mind to use this method only in a company-wide solution, and don't publish to the public. 338 | 339 | ### HockeyApp 340 | 341 | [HockeyApp](https://hockeyapp.net) is a distribution and crash report service, which offers the web server space to download an Ad-hoc or In-House sign build via a website: 342 | 343 | ![](./documentation/images/hockeyapp-download-site.png) 344 | 345 | You only have to upload the _*.ipa_ to the service, and then you can share the link to your product owner. 346 | 347 | #### Fastlane integration 348 | 349 | Fastlane provides with [hockey](https://docs.fastlane.tools/actions/hockey/) a built-in function to upload an _*.ipa_ to the HockeyApp: 350 | 351 | ``` 352 | hockey( 353 | api_token: ENV['HOCKEYAPP_API_TOKEN'], 354 | ipa: lane_context[SharedValues::IPA_OUTPUT_PATH], 355 | dsym: lane_context[SharedValues::DSYM_OUTPUT_PATH] 356 | ) 357 | ``` 358 | 359 | You only have to provide an api token to a HockeyApp app. See [HockeyApp Account](#hockeyapp-account) how to create one. 360 | 361 | ### Testflight & App Store 362 | 363 | For internal and public beta tests is Testflight from Apple the best way. Because you use an App Store signed build for it and need a review for the external beta test, you are very close to a release in the App Store. 364 | 365 | For more information take a lot at the [Testflight](https://developer.apple.com/testflight/) section on Apple's developer site. 366 | 367 | #### Fastlane integration 368 | 369 | With [upload\_to\_testflight](https://docs.fastlane.tools/actions/upload_to_testflight/) fastlane also provides a function to upload an App Store signed _*.ipa_ to App Store Connect. It's used in the fastlane lane [release](./fastlane/Fastfile): 370 | 371 | ``` 372 | lane :release do 373 | build("../signing/release", "Release" ,"app-store") 374 | upload_to_testflight(skip_submission: true) 375 | end 376 | ``` 377 | 378 | If you want manual submit your app to the public beta test set `skip_submission` to _true_. 379 | 380 | To be able to upload an `*.ipa` to App Store Connect, fastlane needs user credentials for it. These will be set as environment variables (see [Environment variables](#environment-variables) section). 381 | To create an App Store Connect user have a look at the [App Store Connect User](#app-store-connect-user) section. 382 | 383 | 384 | ## GitHub Integrations 385 | 386 | Github offers a great web interface to work with multiple developers on a project. How you can organize your flow is for example described in [Understanding the GitHub flow](https://guides.github.com/introduction/flow/). Other flows and conventions are listed in my repository [messeb/development-conventions](https://github.com/messeb/development-conventions). 387 | 388 | The most important part during development, (after writing the code), is the code review in your team. There you can review and discuss implemented solutions. Github provides with its pull request feature ([Creating a pull request](https://help.github.com/articles/creating-a-pull-request/)) a dedicated manner to do it. But the review of code is one of the most challenging parts in software development. Besides the discussion about the main feature, there are always some stressful side discussions about code style, test coverage, and some missing pieces. 389 | 390 | Therefore GitHub provides APIs for the integration of 3rd party service in their pull request. There is also a whole Marketplace for services which can improve the development workflow: [GitHub Marketplace](https://github.com/marketplace). 391 | 392 | The project template uses Danger, HoundCI, and Codecov. With that integrations, you see common warnings and errors already in the pull request, and a reviewer will only check out and review the code when everything else is fine. Therefore it's essential that a ci build is done on any changes of a pull request. It should not be needed to check out a feature branch and build it locally to see that anything obvious is wrong. 393 | 394 | ### Danger 395 | 396 | [Danger](https://danger.systems) is a tool that runs in the ci pipeline and can comment on pull requests if changes in the pull request violate predefined rules. It could look like this: 397 | 398 | ![](./documentation/images/danger-bot-note.png) 399 | 400 | The rules a defined in the [Dangerfile](./Dangerfile) and it uses a GitHub bot user to create that comments ([Creating a bot account for Danger to use](https://danger.systems/guides/getting_started.html#creating-a-bot-account-for-danger-to-use)). But it also supports GitLab and Bitbucket Server. Take a look in the Danger [Getting set up](https://danger.systems/guides/getting_started.html) guide. 401 | 402 | Danger is a big help to concentrate only on the critical parts of the code changes in a review. Because the creator of the pull request gets this warnings direct after a pull request ci build and these can be fixed before another developer have even a look at the code changes. 403 | 404 | Of course, you have to define the rules for the Danger check, but you can add them one time after a discussion in the team, and the same debate will never occur. 405 | Good starting points for fundamental rules are the [Danger Reference](https://danger.systems/reference.html) and a GitHub search for "Dangerfile" ([click](https://github.com/search?q=Dangerfile)). 406 | 407 | The template uses the Ruby version ([Gemfile](Gemfile)) of Danger because you also define your fastlane lanes also in Ruby. Danger is executed through the [Makefile](Makefile) target _pull\_request_ on the build server. 408 | 409 | ### HoundCI 410 | 411 | [HoundCI](https://houndci.com) is a 3rd party service which integrates into the GitHub pull request and checks the Swift source files against linting rules. 412 | 413 | It supports [SwiftLint](https://github.com/realm/SwiftLint), which is the defacto standard for linting Swift files. 414 | If you don't use SwiftLint already, you should have a look at the [rules reference](https://github.com/realm/SwiftLint/blob/master/Rules.md) and see how great it is. After a team agreement, you will have much less discussion about the code style. Also, you can run it locally with your Xcode build, so that the warnings appear during development in Xcode: 415 | 416 | ![](./documentation/images/xcode-swiftlint-warnings.png) 417 | 418 | For the ci build HoundCI will comment inline in the pull request so you will see the linting error direct: 419 | 420 | ![](./documentation/images/houndci-warning.png) 421 | 422 | The configuration of HoundCI is done in the [.hound.yml](.hound.yml) and full documentation of it you will find [HoundCI SwitfLint](http://help.houndci.com/configuration/swiftlint) site. 423 | 424 | ### Codecov 425 | 426 | Tests are essential as the feature code itself. But it's not easy to see if all code paths are covered. Codecov brings visualization of the code coverage in the current pull request: 427 | 428 | ![](./documentation/images/codecov-report.png) 429 | 430 | You will see what code paths are not covered by the tests in the current pull request code and how the code coverage is changed against the base branch. 431 | It uses the code coverage output that `xcodebuild` produces. So you need to enable it in the scheme: 432 | 433 | ![](./documentation/images/xcode-code-coverage.png) 434 | 435 | The configuration of Codecov will be done in the [.codecov.yml](.codecov.yml) file. You will find more information in the [Codecov Guide](https://docs.codecov.io/docs). The upload of the code coverage reports are done in the [Makefile](Makefile) target _codecov\_upload_. 436 | 437 | ## Usage 438 | 439 | To use the template for your own project, you have to change some configurations and contents of files. 440 | 441 | ### Signing 442 | 443 | Create the signing certificates and provisioning profiles for the different builds in the [Certificates, Identifiers & Profiles](https://developer.apple.com/account/ios/certificate/) section of the developer portal. 444 | 445 | Add your unencrypted signing certificate and mobile provision profile for the `Staging` (Folder [signing/staging](signing/staging)) and `Release` (Folder [signing/release](signing/staging)) versions to their folders and delete other existing files. 446 | 447 | Then call in the command line: 448 | 449 | ``` 450 | $ bundle install 451 | $ bundle exec fastlane encrypt 452 | ``` 453 | 454 | You will be asked for an encryption key. After entering, the files will be encrypted with it. Remember the key, it will be set as environment variable `FILE_DECRYPTION_KEY` for the decryption on the build server. 455 | 456 | ### Configuration 457 | 458 | To configure the project for your team and with your bundle identifiers and signing information you have to change only following `*.xcconfig` files. 459 | 460 | **SharedSigning.xcconfig** ([SharedSigning.xcconfig](iOSProject/Configurations/Builds/Signing/SharedSigning.xcconfig)): Change the `DEVELOPMENT_TEAM` to your team id. 461 | 462 | **DebugSigning.xcconfig** ([DebugSigning.xcconfig](iOSProject/Configurations/Builds/Signing/DebugSigning.xcconfig)): Change the `PRODUCT_BUNDLE_IDENTIFIER` to the bundle identifier for your local development. 463 | 464 | **StagingSigning.xcconfig** ([StagingSigning.xcconfig](iOSProject/Configurations/Builds/Signing/StagingSigning.xcconfig)): Change the `PRODUCT_BUNDLE_IDENTIFIER` to the bundle identifier for your staging build. Also set `CODE_SIGN_IDENTITY` and `PROVISIONING_PROFILE_SPECIFIER` to the names of the signing identity and the mobile provisioning profile for the staging build. 465 | 466 | **ReleaseSigning.xcconfig** ([ReleaseSigning.xcconfig](iOSProject/Configurations/Builds/Signing/ReleaseSigning.xcconfig)): Change the `PRODUCT_BUNDLE_IDENTIFIER` to the bundle identifier for your App Store build. Also, set `CODE_SIGN_IDENTITY` and `PROVISIONING_PROFILE_SPECIFIER` to the names of the signing identity and the mobile provisioning profile for the App Store build. 467 | 468 | ### HockeyApp Account 469 | 470 | Create a free HockeyApp account on [https://hockeyapp.net/](https://hockeyapp.net/) and add a new iOS distribution app on the [Dashboard](https://rink.hockeyapp.net/manage/dashboard). 471 | 472 | ![](./documentation/images/hockeyapp-dashboard.png) 473 | 474 | Generate an API Token for your created distribution app on the [Create API Token](https://rink.hockeyapp.net/manage/auth_tokens) page and set the environment variable `HOCKEYAPP_API_TOKEN` to that value. 475 | 476 | ![](./documentation/images/hockeyapp-app-token.png) 477 | 478 | ### App Store Connect User 479 | 480 | To upload the app artifact for the App Store via fastlane, it needs credentials for an App Store Connect app. 481 | Create a new App Store connect user in the [User and Access](https://appstoreconnect.apple.com/access/users) section for the usage with fastlane. 482 | 483 | It should have the _Developer_ role and only access to the needed apps. 484 | 485 | ![](./documentation/images/app-store-connect-user.png) 486 | 487 | Set the environment variables `FASTLANE_USER` with the email address and `FASTLANE_PASSWORD` with the password of the App Store Connect user. 488 | 489 | ### GitHub 490 | 491 | To use the GitHub integrations, you have to configure accounts and setup some service. 492 | 493 | **Danger**: To use Danger, create a new GitHub Account like my bot ([messeb-bot](https://github.com/messeb-bot)), generate a personal token in the [Developer Settings](https://github.com/settings/tokens) and assign it to the environment variable `DANGER_GITHUB_API_TOKEN` 494 | 495 | **HoundCI**: Go to the website [https://houndci.com](https://houndci.com) and log in with your GitHub Account. Then you can connect your repositories with HoundCI. 496 | 497 | **Codecov**: To integrate Codecov in your visit the [Codecov Marketplace site](https://github.com/marketplace/codecov) and add it to your repository. On the Codecov site you can then access the *Settings* page of the repository. Set the value of **Repository Upload Token** to the environment variable `CODECOV_TOKEN`. 498 | 499 | ### Makefile 500 | 501 | Uncomment in the [Makefile](Makefile) the target of the `staging` and `release` build to: 502 | 503 | ``` 504 | staging: 505 | bundle exec fastlane staging 506 | 507 | release: 508 | bundle exec fastlane release 509 | ``` -------------------------------------------------------------------------------- /documentation/images/app-store-connect-user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/app-store-connect-user.png -------------------------------------------------------------------------------- /documentation/images/codecov-report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/codecov-report.png -------------------------------------------------------------------------------- /documentation/images/danger-bot-note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/danger-bot-note.png -------------------------------------------------------------------------------- /documentation/images/hockeyapp-app-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/hockeyapp-app-token.png -------------------------------------------------------------------------------- /documentation/images/hockeyapp-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/hockeyapp-dashboard.png -------------------------------------------------------------------------------- /documentation/images/hockeyapp-download-site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/hockeyapp-download-site.png -------------------------------------------------------------------------------- /documentation/images/houndci-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/houndci-warning.png -------------------------------------------------------------------------------- /documentation/images/ios-project-template-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/ios-project-template-logo.png -------------------------------------------------------------------------------- /documentation/images/travis-ci-environment-variables.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/travis-ci-environment-variables.png -------------------------------------------------------------------------------- /documentation/images/travis-ci-repository-selection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/travis-ci-repository-selection.png -------------------------------------------------------------------------------- /documentation/images/xcode-build-settings-xcconfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-build-settings-xcconfig.png -------------------------------------------------------------------------------- /documentation/images/xcode-code-coverage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-code-coverage.png -------------------------------------------------------------------------------- /documentation/images/xcode-embedded-binaries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-embedded-binaries.png -------------------------------------------------------------------------------- /documentation/images/xcode-framework-carthage-linking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-framework-carthage-linking.png -------------------------------------------------------------------------------- /documentation/images/xcode-main-interface-reference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-main-interface-reference.png -------------------------------------------------------------------------------- /documentation/images/xcode-project-configuration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-project-configuration.png -------------------------------------------------------------------------------- /documentation/images/xcode-project-structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-project-structure.png -------------------------------------------------------------------------------- /documentation/images/xcode-swiftlint-warnings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-swiftlint-warnings.png -------------------------------------------------------------------------------- /documentation/images/xcode-xcconfig-files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/documentation/images/xcode-xcconfig-files.png -------------------------------------------------------------------------------- /fastlane/.gitignore: -------------------------------------------------------------------------------- 1 | test_output 2 | report.xml 3 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | require './libs/encryption.rb' 2 | require './libs/signing.rb' 3 | 4 | default_platform(:ios) 5 | 6 | platform :ios do 7 | 8 | lane :test do 9 | run_tests(scheme: 'iOSProject') 10 | end 11 | 12 | lane :staging do 13 | build("../signing/staging", "Staging" ,"ad-hoc") 14 | staging_upload 15 | end 16 | 17 | lane :release do 18 | build("../signing/release", "Release" ,"app-store") 19 | upload_to_testflight(skip_submission: true) 20 | end 21 | 22 | lane :encrypt do 23 | key = prompt( 24 | text: "Encryption key: ", 25 | secure_text: true 26 | ) 27 | encrypt("../signing/staging", key) 28 | encrypt("../signing/release", key) 29 | end 30 | 31 | def build(folder, configuration, export_method) 32 | create_signing_configuration(folder, ENV['FILE_DECRYPTION_KEY']) 33 | 34 | increment_build_number(build_number: number_of_commits(all: true)) 35 | 36 | build_ios_app( 37 | scheme: 'iOSProject', 38 | export_method: export_method, 39 | configuration: configuration 40 | ) 41 | 42 | clear_signing_configuration(folder) 43 | end 44 | 45 | def staging_upload() 46 | hockey( 47 | api_token: ENV['HOCKEYAPP_API_TOKEN'], 48 | ipa: lane_context[SharedValues::IPA_OUTPUT_PATH], 49 | dsym: lane_context[SharedValues::DSYM_OUTPUT_PATH] 50 | ) 51 | end 52 | end -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | Install _fastlane_ using 12 | ``` 13 | [sudo] gem install fastlane -NV 14 | ``` 15 | or alternatively using `brew cask install fastlane` 16 | 17 | # Available Actions 18 | ## iOS 19 | ### ios test 20 | ``` 21 | fastlane ios test 22 | ``` 23 | 24 | ### ios staging 25 | ``` 26 | fastlane ios staging 27 | ``` 28 | 29 | ### ios release 30 | ``` 31 | fastlane ios release 32 | ``` 33 | 34 | ### ios encrypt 35 | ``` 36 | fastlane ios encrypt 37 | ``` 38 | 39 | 40 | ---- 41 | 42 | This README.md is auto-generated and will be re-generated every time [fastlane](https://fastlane.tools) is run. 43 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 44 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 45 | -------------------------------------------------------------------------------- /fastlane/libs/encryption.rb: -------------------------------------------------------------------------------- 1 | require 'openssl' 2 | 3 | # Encrypts all files of a folder 4 | # 5 | # @param folder Folder of the certificate and provisioning profile 6 | # @param key Encryption key for the certificate and provisioning profile 7 | def encrypt(folder, key) 8 | Dir.each_child(folder) do | child | 9 | unless File.extname(child) != ".enc" 10 | next 11 | end 12 | 13 | cipher = OpenSSL::Cipher::AES256.new :CBC 14 | cipher.encrypt 15 | cipher.key = Digest::SHA256.digest key 16 | 17 | file = File.absolute_path(child, folder) 18 | content = File.open(file, "rb").read 19 | 20 | encrypted_content = cipher.update(content) + cipher.final 21 | 22 | output_file = File.absolute_path(child + ".enc", folder) 23 | File.open(output_file, "w").write(encrypted_content) 24 | end 25 | end 26 | 27 | # Decrypts all files of a folder 28 | # 29 | # @param folder Folder of the certificate and provisioning profile 30 | # @param key Decryption key for the certificate and provisioning profile 31 | def decrypt(folder, key) 32 | Dir.each_child(folder) do | child | 33 | unless File.extname(child) == ".enc" 34 | next 35 | end 36 | 37 | puts child 38 | decipher = OpenSSL::Cipher::AES256.new :CBC 39 | decipher.decrypt 40 | decipher.key = Digest::SHA256.digest key 41 | 42 | file = File.absolute_path(child, folder) 43 | content = File.open(file, "rb").read 44 | 45 | decrypted_content = decipher.update(content) + decipher.final 46 | 47 | output_file_path = File.absolute_path(File.basename(child, ".enc"), folder) 48 | output_file = File.open(output_file_path, "w") 49 | output_file.sync = true 50 | output_file.write(decrypted_content) 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /fastlane/libs/signing.rb: -------------------------------------------------------------------------------- 1 | require './libs/encryption.rb' 2 | 3 | # Creates the signing configuration for the build. 4 | # 5 | # @param folder Folder of the certificate and provisioning profile 6 | # @param key Decryption key for the certificate and provisioning profile 7 | def create_signing_configuration(folder, key) 8 | decrypt(folder, key) 9 | 10 | keychain_name = 'ios_build.keychain' 11 | keychain_password = key # only for temporary use 12 | 13 | create_keychain({ 14 | name: keychain_name, 15 | password: keychain_password, 16 | }) 17 | 18 | unlock_keychain({ 19 | path: FastlaneCore::Helper.keychain_path(keychain_name), 20 | add_to_search_list: true, 21 | set_default: true, 22 | password: keychain_password 23 | }) 24 | 25 | import_certificates_in_keychain( 26 | folder, 27 | FastlaneCore::Helper.keychain_path(keychain_name), 28 | keychain_password 29 | ) 30 | 31 | copy_mobile_provisioning_profiles(folder) 32 | end 33 | 34 | # Imports certificates from a folder to the keychain 35 | # 36 | # @param folder Folder of the certificate and provisioning profile 37 | # @param keychain_path Path for the temporary keychain 38 | # @param keychain_password Password for the temporary keychain 39 | def import_certificates_in_keychain(folder, keychain_path, keychain_password) 40 | supported_extensions = [".p12", ".cer"] 41 | 42 | Find.find(folder) do |file| 43 | next if !supported_extensions.include?(File.extname(file)) 44 | 45 | puts "import: " + file 46 | 47 | FastlaneCore::KeychainImporter.import_file( 48 | file, 49 | keychain_path, 50 | keychain_password: keychain_password, 51 | output: FastlaneCore::Globals.verbose?) 52 | end 53 | end 54 | 55 | # Copies mobile provisioning profiles from a folder to the Provisioning Profiles folder 56 | # 57 | # @param folder Folder of the certificate and provisioning profile 58 | def copy_mobile_provisioning_profiles(folder) 59 | supported_extensions = [".mobileprovision"] 60 | 61 | Find.find(folder) do |file| 62 | next if !supported_extensions.include?(File.extname(file)) 63 | basename = File.basename(file) 64 | 65 | FileUtils.mkdir_p("#{Dir.home}/Library/MobileDevice/Provisioning\ Profiles/") 66 | FileUtils.cp(file, "#{Dir.home}/Library/MobileDevice/Provisioning\ Profiles/#{basename}") 67 | end 68 | end 69 | 70 | # Removes the temporary keychain 71 | def remove_keychain 72 | keychain_name = 'ios_build.keychain' 73 | 74 | delete_keychain ({ 75 | name: keychain_name 76 | }) 77 | end 78 | 79 | # Deletes encrypted certificates for a configuration 80 | # 81 | # @param configuration Configuration for the build 82 | def delete_certificates(folder) 83 | supported_extensions = [".p12", ".cer"] 84 | 85 | Find.find(folder) do |file| 86 | next if !supported_extensions.include?(File.extname(file)) 87 | 88 | FileUtils.rm(file) 89 | end 90 | end 91 | 92 | # Deletes encrypted mobile provisioning profiles 93 | # 94 | # @param configuration Configuration for the build 95 | def delete_mobile_provisioning_profiles(folder) 96 | supported_extensions = [".mobileprovision"] 97 | 98 | Find.find(folder) do |file| 99 | next if !supported_extensions.include?(File.extname(file)) 100 | 101 | FileUtils.rm(file) 102 | end 103 | end 104 | 105 | # Clears the signing configuration and deletes the certificates, profiles and keychains 106 | # 107 | # @param configuration Configuration for the build 108 | def clear_signing_configuration(folder) 109 | delete_certificates(folder) 110 | delete_mobile_provisioning_profiles(folder) 111 | remove_keychain 112 | end 113 | -------------------------------------------------------------------------------- /iOSProject.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 51; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E01BC7222148DA24004BB3A4 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E0C82F2F21478A4B009EA559 /* Alamofire.framework */; }; 11 | E01BC7292148DA4C004BB3A4 /* Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E01BC7272148DA45004BB3A4 /* Core.framework */; }; 12 | E01BC72A2148DA4C004BB3A4 /* Core.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E01BC7272148DA45004BB3A4 /* Core.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 13 | E0FD11FD21477D0A008C2EF8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E0FD11FC21477D0A008C2EF8 /* LaunchScreen.storyboard */; }; 14 | E0FD11FF21477D1C008C2EF8 /* Assests.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E0FD11FE21477D1C008C2EF8 /* Assests.xcassets */; }; 15 | E0FD121E214783B2008C2EF8 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0FD121C214783B2008C2EF8 /* main.swift */; }; 16 | E0FD121F214783B2008C2EF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0FD121D214783B2008C2EF8 /* AppDelegate.swift */; }; 17 | E0FD1222214783F1008C2EF8 /* iOSProjectTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0FD1221214783F1008C2EF8 /* iOSProjectTests.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | E0FD11C521477965008C2EF8 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = E0FD11A821477963008C2EF8 /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = E0FD11AF21477963008C2EF8; 26 | remoteInfo = iOSProject; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXCopyFilesBuildPhase section */ 31 | E01BC7262148DA3A004BB3A4 /* Embed Frameworks */ = { 32 | isa = PBXCopyFilesBuildPhase; 33 | buildActionMask = 2147483647; 34 | dstPath = ""; 35 | dstSubfolderSpec = 10; 36 | files = ( 37 | E01BC72A2148DA4C004BB3A4 /* Core.framework in Embed Frameworks */, 38 | ); 39 | name = "Embed Frameworks"; 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXCopyFilesBuildPhase section */ 43 | 44 | /* Begin PBXFileReference section */ 45 | E01BC7272148DA45004BB3A4 /* Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Core.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | E0C82F2F21478A4B009EA559 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = ""; }; 47 | E0FD11B021477963008C2EF8 /* iOSProject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSProject.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | E0FD11C421477965008C2EF8 /* iOSProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iOSProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | E0FD11FC21477D0A008C2EF8 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 50 | E0FD11FE21477D1C008C2EF8 /* Assests.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assests.xcassets; sourceTree = ""; }; 51 | E0FD120021477D29008C2EF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | E0FD1202214781CA008C2EF8 /* ReleaseTest.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseTest.xcconfig; sourceTree = ""; }; 53 | E0FD1203214781CA008C2EF8 /* Staging.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Staging.xcconfig; sourceTree = ""; }; 54 | E0FD1204214781CA008C2EF8 /* SharedTest.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = SharedTest.xcconfig; sourceTree = ""; }; 55 | E0FD1205214781CA008C2EF8 /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; 56 | E0FD1206214781CA008C2EF8 /* Shared.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = ""; }; 57 | E0FD1207214781CA008C2EF8 /* Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 58 | E0FD1208214781CA008C2EF8 /* Application.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Application.xcconfig; sourceTree = ""; }; 59 | E0FD1209214781CA008C2EF8 /* StagingTest.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = StagingTest.xcconfig; sourceTree = ""; }; 60 | E0FD120A214781CA008C2EF8 /* DebugTest.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugTest.xcconfig; sourceTree = ""; }; 61 | E0FD1214214781D2008C2EF8 /* DebugSigning.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugSigning.xcconfig; sourceTree = ""; }; 62 | E0FD1215214781D2008C2EF8 /* ReleaseSigning.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = ReleaseSigning.xcconfig; sourceTree = ""; }; 63 | E0FD1216214781D2008C2EF8 /* SharedSigning.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = SharedSigning.xcconfig; sourceTree = ""; }; 64 | E0FD1217214781D2008C2EF8 /* StagingSigning.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = StagingSigning.xcconfig; sourceTree = ""; }; 65 | E0FD121C214783B2008C2EF8 /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 66 | E0FD121D214783B2008C2EF8 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 67 | E0FD1220214783E9008C2EF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 68 | E0FD1221214783F1008C2EF8 /* iOSProjectTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = iOSProjectTests.swift; sourceTree = ""; }; 69 | /* End PBXFileReference section */ 70 | 71 | /* Begin PBXFrameworksBuildPhase section */ 72 | E0FD11AD21477963008C2EF8 /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | E01BC7292148DA4C004BB3A4 /* Core.framework in Frameworks */, 77 | E01BC7222148DA24004BB3A4 /* Alamofire.framework in Frameworks */, 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | E0FD11C121477965008C2EF8 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | E0BB8FB721695633001922DE /* Scenes */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | ); 95 | path = Scenes; 96 | sourceTree = ""; 97 | }; 98 | E0C82F2E21478A4B009EA559 /* Frameworks */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | E01BC7272148DA45004BB3A4 /* Core.framework */, 102 | E0C82F2F21478A4B009EA559 /* Alamofire.framework */, 103 | ); 104 | name = Frameworks; 105 | sourceTree = ""; 106 | }; 107 | E0FD11A721477963008C2EF8 = { 108 | isa = PBXGroup; 109 | children = ( 110 | E0FD11B221477963008C2EF8 /* iOSProject */, 111 | E0FD11C721477965008C2EF8 /* iOSProjectTests */, 112 | E0FD11B121477963008C2EF8 /* Products */, 113 | E0C82F2E21478A4B009EA559 /* Frameworks */, 114 | ); 115 | sourceTree = ""; 116 | }; 117 | E0FD11B121477963008C2EF8 /* Products */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | E0FD11B021477963008C2EF8 /* iOSProject.app */, 121 | E0FD11C421477965008C2EF8 /* iOSProjectTests.xctest */, 122 | ); 123 | name = Products; 124 | sourceTree = ""; 125 | }; 126 | E0FD11B221477963008C2EF8 /* iOSProject */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | E0BB8FB721695633001922DE /* Scenes */, 130 | E0FD11F821477C98008C2EF8 /* Resources */, 131 | E0FD11F721477C92008C2EF8 /* Configurations */, 132 | E0FD121D214783B2008C2EF8 /* AppDelegate.swift */, 133 | E0FD121C214783B2008C2EF8 /* main.swift */, 134 | ); 135 | path = iOSProject; 136 | sourceTree = ""; 137 | }; 138 | E0FD11C721477965008C2EF8 /* iOSProjectTests */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | E0FD11FA21477CB2008C2EF8 /* Tests */, 142 | E0FD11F921477CAB008C2EF8 /* Configurations */, 143 | ); 144 | path = iOSProjectTests; 145 | sourceTree = ""; 146 | }; 147 | E0FD11F721477C92008C2EF8 /* Configurations */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | E0FD11FB21477CCB008C2EF8 /* Builds */, 151 | E0FD120021477D29008C2EF8 /* Info.plist */, 152 | ); 153 | path = Configurations; 154 | sourceTree = ""; 155 | }; 156 | E0FD11F821477C98008C2EF8 /* Resources */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | E0FD11FC21477D0A008C2EF8 /* LaunchScreen.storyboard */, 160 | E0FD11FE21477D1C008C2EF8 /* Assests.xcassets */, 161 | ); 162 | path = Resources; 163 | sourceTree = ""; 164 | }; 165 | E0FD11F921477CAB008C2EF8 /* Configurations */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | E0FD1220214783E9008C2EF8 /* Info.plist */, 169 | ); 170 | path = Configurations; 171 | sourceTree = ""; 172 | }; 173 | E0FD11FA21477CB2008C2EF8 /* Tests */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | E0FD1221214783F1008C2EF8 /* iOSProjectTests.swift */, 177 | ); 178 | path = Tests; 179 | sourceTree = ""; 180 | }; 181 | E0FD11FB21477CCB008C2EF8 /* Builds */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | E0FD1208214781CA008C2EF8 /* Application.xcconfig */, 185 | E0FD1205214781CA008C2EF8 /* Debug.xcconfig */, 186 | E0FD120A214781CA008C2EF8 /* DebugTest.xcconfig */, 187 | E0FD1207214781CA008C2EF8 /* Release.xcconfig */, 188 | E0FD1202214781CA008C2EF8 /* ReleaseTest.xcconfig */, 189 | E0FD1206214781CA008C2EF8 /* Shared.xcconfig */, 190 | E0FD1204214781CA008C2EF8 /* SharedTest.xcconfig */, 191 | E0FD1203214781CA008C2EF8 /* Staging.xcconfig */, 192 | E0FD1209214781CA008C2EF8 /* StagingTest.xcconfig */, 193 | E0FD12012147817C008C2EF8 /* Signing */, 194 | ); 195 | path = Builds; 196 | sourceTree = ""; 197 | }; 198 | E0FD12012147817C008C2EF8 /* Signing */ = { 199 | isa = PBXGroup; 200 | children = ( 201 | E0FD1214214781D2008C2EF8 /* DebugSigning.xcconfig */, 202 | E0FD1215214781D2008C2EF8 /* ReleaseSigning.xcconfig */, 203 | E0FD1216214781D2008C2EF8 /* SharedSigning.xcconfig */, 204 | E0FD1217214781D2008C2EF8 /* StagingSigning.xcconfig */, 205 | ); 206 | path = Signing; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXGroup section */ 210 | 211 | /* Begin PBXNativeTarget section */ 212 | E0FD11AF21477963008C2EF8 /* iOSProject */ = { 213 | isa = PBXNativeTarget; 214 | buildConfigurationList = E0FD11CD21477965008C2EF8 /* Build configuration list for PBXNativeTarget "iOSProject" */; 215 | buildPhases = ( 216 | E0C82F2621478981009EA559 /* Carthage */, 217 | E0C82F2521478957009EA559 /* SwiftLint */, 218 | E0FD11AC21477963008C2EF8 /* Sources */, 219 | E0FD11AD21477963008C2EF8 /* Frameworks */, 220 | E0FD11AE21477963008C2EF8 /* Resources */, 221 | E01BC7262148DA3A004BB3A4 /* Embed Frameworks */, 222 | ); 223 | buildRules = ( 224 | ); 225 | dependencies = ( 226 | ); 227 | name = iOSProject; 228 | productName = iOSProject; 229 | productReference = E0FD11B021477963008C2EF8 /* iOSProject.app */; 230 | productType = "com.apple.product-type.application"; 231 | }; 232 | E0FD11C321477965008C2EF8 /* iOSProjectTests */ = { 233 | isa = PBXNativeTarget; 234 | buildConfigurationList = E0FD11D021477965008C2EF8 /* Build configuration list for PBXNativeTarget "iOSProjectTests" */; 235 | buildPhases = ( 236 | E0FD11C021477965008C2EF8 /* Sources */, 237 | E0FD11C121477965008C2EF8 /* Frameworks */, 238 | E0FD11C221477965008C2EF8 /* Resources */, 239 | ); 240 | buildRules = ( 241 | ); 242 | dependencies = ( 243 | E0FD11C621477965008C2EF8 /* PBXTargetDependency */, 244 | ); 245 | name = iOSProjectTests; 246 | productName = iOSProjectTests; 247 | productReference = E0FD11C421477965008C2EF8 /* iOSProjectTests.xctest */; 248 | productType = "com.apple.product-type.bundle.unit-test"; 249 | }; 250 | /* End PBXNativeTarget section */ 251 | 252 | /* Begin PBXProject section */ 253 | E0FD11A821477963008C2EF8 /* Project object */ = { 254 | isa = PBXProject; 255 | attributes = { 256 | LastSwiftUpdateCheck = 1000; 257 | LastUpgradeCheck = 1100; 258 | ORGANIZATIONNAME = messeb.com; 259 | TargetAttributes = { 260 | E0FD11AF21477963008C2EF8 = { 261 | CreatedOnToolsVersion = 10.0; 262 | LastSwiftMigration = 1000; 263 | }; 264 | E0FD11C321477965008C2EF8 = { 265 | CreatedOnToolsVersion = 10.0; 266 | LastSwiftMigration = 1100; 267 | TestTargetID = E0FD11AF21477963008C2EF8; 268 | }; 269 | }; 270 | }; 271 | buildConfigurationList = E0FD11AB21477963008C2EF8 /* Build configuration list for PBXProject "iOSProject" */; 272 | compatibilityVersion = "Xcode 10.0"; 273 | developmentRegion = en; 274 | hasScannedForEncodings = 0; 275 | knownRegions = ( 276 | en, 277 | Base, 278 | ); 279 | mainGroup = E0FD11A721477963008C2EF8; 280 | productRefGroup = E0FD11B121477963008C2EF8 /* Products */; 281 | projectDirPath = ""; 282 | projectRoot = ""; 283 | targets = ( 284 | E0FD11AF21477963008C2EF8 /* iOSProject */, 285 | E0FD11C321477965008C2EF8 /* iOSProjectTests */, 286 | ); 287 | }; 288 | /* End PBXProject section */ 289 | 290 | /* Begin PBXResourcesBuildPhase section */ 291 | E0FD11AE21477963008C2EF8 /* Resources */ = { 292 | isa = PBXResourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | E0FD11FF21477D1C008C2EF8 /* Assests.xcassets in Resources */, 296 | E0FD11FD21477D0A008C2EF8 /* LaunchScreen.storyboard in Resources */, 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | }; 300 | E0FD11C221477965008C2EF8 /* Resources */ = { 301 | isa = PBXResourcesBuildPhase; 302 | buildActionMask = 2147483647; 303 | files = ( 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | /* End PBXResourcesBuildPhase section */ 308 | 309 | /* Begin PBXShellScriptBuildPhase section */ 310 | E0C82F2521478957009EA559 /* SwiftLint */ = { 311 | isa = PBXShellScriptBuildPhase; 312 | buildActionMask = 2147483647; 313 | files = ( 314 | ); 315 | inputFileListPaths = ( 316 | ); 317 | inputPaths = ( 318 | ); 319 | name = SwiftLint; 320 | outputFileListPaths = ( 321 | ); 322 | outputPaths = ( 323 | ); 324 | runOnlyForDeploymentPostprocessing = 0; 325 | shellPath = /bin/sh; 326 | shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; 327 | }; 328 | E0C82F2621478981009EA559 /* Carthage */ = { 329 | isa = PBXShellScriptBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | ); 333 | inputFileListPaths = ( 334 | ); 335 | inputPaths = ( 336 | "$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework", 337 | ); 338 | name = Carthage; 339 | outputFileListPaths = ( 340 | ); 341 | outputPaths = ( 342 | "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Alamofire.framework", 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | shellPath = /bin/sh; 346 | shellScript = "/usr/local/bin/carthage copy-frameworks\n"; 347 | }; 348 | /* End PBXShellScriptBuildPhase section */ 349 | 350 | /* Begin PBXSourcesBuildPhase section */ 351 | E0FD11AC21477963008C2EF8 /* Sources */ = { 352 | isa = PBXSourcesBuildPhase; 353 | buildActionMask = 2147483647; 354 | files = ( 355 | E0FD121F214783B2008C2EF8 /* AppDelegate.swift in Sources */, 356 | E0FD121E214783B2008C2EF8 /* main.swift in Sources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | E0FD11C021477965008C2EF8 /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | E0FD1222214783F1008C2EF8 /* iOSProjectTests.swift in Sources */, 365 | ); 366 | runOnlyForDeploymentPostprocessing = 0; 367 | }; 368 | /* End PBXSourcesBuildPhase section */ 369 | 370 | /* Begin PBXTargetDependency section */ 371 | E0FD11C621477965008C2EF8 /* PBXTargetDependency */ = { 372 | isa = PBXTargetDependency; 373 | target = E0FD11AF21477963008C2EF8 /* iOSProject */; 374 | targetProxy = E0FD11C521477965008C2EF8 /* PBXContainerItemProxy */; 375 | }; 376 | /* End PBXTargetDependency section */ 377 | 378 | /* Begin XCBuildConfiguration section */ 379 | E0C82F4621478B2D009EA559 /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | baseConfigurationReference = E0FD1208214781CA008C2EF8 /* Application.xcconfig */; 382 | buildSettings = { 383 | MTL_ENABLE_DEBUG_INFO = NO; 384 | MTL_FAST_MATH = YES; 385 | SWIFT_COMPILATION_MODE = wholemodule; 386 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 387 | }; 388 | name = Release; 389 | }; 390 | E0C82F4721478B2D009EA559 /* Release */ = { 391 | isa = XCBuildConfiguration; 392 | baseConfigurationReference = E0FD1207214781CA008C2EF8 /* Release.xcconfig */; 393 | buildSettings = { 394 | CLANG_ENABLE_MODULES = YES; 395 | CURRENT_PROJECT_VERSION = 1; 396 | FRAMEWORK_SEARCH_PATHS = ( 397 | "$(inherited)", 398 | "$(PROJECT_DIR)/Carthage/Build/iOS", 399 | ); 400 | LD_RUNPATH_SEARCH_PATHS = ( 401 | "$(inherited)", 402 | "@executable_path/Frameworks", 403 | ); 404 | MARKETING_VERSION = 1.0; 405 | SWIFT_VERSION = 5.0; 406 | }; 407 | name = Release; 408 | }; 409 | E0C82F4821478B2D009EA559 /* Release */ = { 410 | isa = XCBuildConfiguration; 411 | baseConfigurationReference = E0FD1202214781CA008C2EF8 /* ReleaseTest.xcconfig */; 412 | buildSettings = { 413 | }; 414 | name = Release; 415 | }; 416 | E0FD11CB21477965008C2EF8 /* Debug */ = { 417 | isa = XCBuildConfiguration; 418 | baseConfigurationReference = E0FD1208214781CA008C2EF8 /* Application.xcconfig */; 419 | buildSettings = { 420 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 421 | MTL_FAST_MATH = YES; 422 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 423 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 424 | }; 425 | name = Debug; 426 | }; 427 | E0FD11CC21477965008C2EF8 /* Staging */ = { 428 | isa = XCBuildConfiguration; 429 | baseConfigurationReference = E0FD1208214781CA008C2EF8 /* Application.xcconfig */; 430 | buildSettings = { 431 | MTL_ENABLE_DEBUG_INFO = NO; 432 | MTL_FAST_MATH = YES; 433 | SWIFT_COMPILATION_MODE = wholemodule; 434 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 435 | }; 436 | name = Staging; 437 | }; 438 | E0FD11CE21477965008C2EF8 /* Debug */ = { 439 | isa = XCBuildConfiguration; 440 | baseConfigurationReference = E0FD1205214781CA008C2EF8 /* Debug.xcconfig */; 441 | buildSettings = { 442 | CLANG_ENABLE_MODULES = YES; 443 | CURRENT_PROJECT_VERSION = 1; 444 | FRAMEWORK_SEARCH_PATHS = ( 445 | "$(inherited)", 446 | "$(PROJECT_DIR)/Carthage/Build/iOS", 447 | ); 448 | LD_RUNPATH_SEARCH_PATHS = ( 449 | "$(inherited)", 450 | "@executable_path/Frameworks", 451 | ); 452 | MARKETING_VERSION = 1.0; 453 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 454 | SWIFT_VERSION = 5.0; 455 | }; 456 | name = Debug; 457 | }; 458 | E0FD11CF21477965008C2EF8 /* Staging */ = { 459 | isa = XCBuildConfiguration; 460 | baseConfigurationReference = E0FD1203214781CA008C2EF8 /* Staging.xcconfig */; 461 | buildSettings = { 462 | CLANG_ENABLE_MODULES = YES; 463 | CURRENT_PROJECT_VERSION = 1; 464 | FRAMEWORK_SEARCH_PATHS = ( 465 | "$(inherited)", 466 | "$(PROJECT_DIR)/Carthage/Build/iOS", 467 | ); 468 | LD_RUNPATH_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "@executable_path/Frameworks", 471 | ); 472 | MARKETING_VERSION = 1.0; 473 | SWIFT_VERSION = 5.0; 474 | }; 475 | name = Staging; 476 | }; 477 | E0FD11D121477965008C2EF8 /* Debug */ = { 478 | isa = XCBuildConfiguration; 479 | baseConfigurationReference = E0FD120A214781CA008C2EF8 /* DebugTest.xcconfig */; 480 | buildSettings = { 481 | }; 482 | name = Debug; 483 | }; 484 | E0FD11D221477965008C2EF8 /* Staging */ = { 485 | isa = XCBuildConfiguration; 486 | baseConfigurationReference = E0FD1209214781CA008C2EF8 /* StagingTest.xcconfig */; 487 | buildSettings = { 488 | }; 489 | name = Staging; 490 | }; 491 | /* End XCBuildConfiguration section */ 492 | 493 | /* Begin XCConfigurationList section */ 494 | E0FD11AB21477963008C2EF8 /* Build configuration list for PBXProject "iOSProject" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | E0FD11CB21477965008C2EF8 /* Debug */, 498 | E0FD11CC21477965008C2EF8 /* Staging */, 499 | E0C82F4621478B2D009EA559 /* Release */, 500 | ); 501 | defaultConfigurationIsVisible = 0; 502 | defaultConfigurationName = Staging; 503 | }; 504 | E0FD11CD21477965008C2EF8 /* Build configuration list for PBXNativeTarget "iOSProject" */ = { 505 | isa = XCConfigurationList; 506 | buildConfigurations = ( 507 | E0FD11CE21477965008C2EF8 /* Debug */, 508 | E0FD11CF21477965008C2EF8 /* Staging */, 509 | E0C82F4721478B2D009EA559 /* Release */, 510 | ); 511 | defaultConfigurationIsVisible = 0; 512 | defaultConfigurationName = Staging; 513 | }; 514 | E0FD11D021477965008C2EF8 /* Build configuration list for PBXNativeTarget "iOSProjectTests" */ = { 515 | isa = XCConfigurationList; 516 | buildConfigurations = ( 517 | E0FD11D121477965008C2EF8 /* Debug */, 518 | E0FD11D221477965008C2EF8 /* Staging */, 519 | E0C82F4821478B2D009EA559 /* Release */, 520 | ); 521 | defaultConfigurationIsVisible = 0; 522 | defaultConfigurationName = Staging; 523 | }; 524 | /* End XCConfigurationList section */ 525 | }; 526 | rootObject = E0FD11A821477963008C2EF8 /* Project object */; 527 | } 528 | -------------------------------------------------------------------------------- /iOSProject.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /iOSProject.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iOSProject.xcodeproj/xcshareddata/xcschemes/iOSProject.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 39 | 40 | 41 | 42 | 48 | 49 | 55 | 56 | 57 | 58 | 60 | 66 | 67 | 68 | 70 | 76 | 77 | 78 | 79 | 80 | 90 | 92 | 98 | 99 | 100 | 101 | 107 | 109 | 115 | 116 | 117 | 118 | 120 | 121 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /iOSProject.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /iOSProject.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /iOSProject/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Core 3 | import Alamofire 4 | 5 | class AppDelegate: UIResponder, UIApplicationDelegate { 6 | 7 | var window: UIWindow? 8 | 9 | func application(_ application: UIApplication, 10 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 11 | window = UIWindow(frame: UIScreen.main.bounds) 12 | 13 | let viewController = UIViewController() 14 | viewController.view.backgroundColor = Core.backgroundColor 15 | 16 | window?.rootViewController = viewController 17 | window?.makeKeyAndVisible() 18 | 19 | return true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Application.xcconfig: -------------------------------------------------------------------------------- 1 | // Architectures 2 | SDKROOT = iphoneos 3 | 4 | // Deployment 5 | COPY_PHASE_STRIP = NO 6 | IPHONEOS_DEPLOYMENT_TARGET = 12.0 7 | 8 | // Search Paths 9 | ALWAYS_SEARCH_USER_PATHS = NO 10 | 11 | // Signing 12 | CODE_SIGN_IDENTITY = iPhone Developer 13 | 14 | // Versioning 15 | VERSIONING_SYSTEM = apple-generic 16 | 17 | // Apple LLVM 9.0 - Code Generation 18 | GCC_DYNAMIC_NO_PIC = NO 19 | GCC_NO_COMMON_BLOCKS = YES 20 | 21 | // Apple LLVM 9.0 - Language 22 | GCC_C_LANGUAGE_STANDARD = gnu11 23 | 24 | // Apple LLVM 9.0 - Language - C++ 25 | CLANG_CXX_LANGUAGE_STANDARD = gnu++14 26 | CLANG_CXX_LIBRARY = libc++ 27 | 28 | // Apple LLVM 9.0 - Language - Modules 29 | CLANG_ENABLE_MODULES = YES 30 | 31 | // Apple LLVM 9.0 - Language - Objective C 32 | CLANG_ENABLE_OBJC_ARC = YES 33 | CLANG_ENABLE_OBJC_WEAK = YES 34 | 35 | // Apple LLVM 9.0 - Language - Preprocessing 36 | ENABLE_STRICT_OBJC_MSGSEND = YES 37 | 38 | // Apple LLVM 9.0 - Warnings - All languages 39 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES 40 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES 41 | CLANG_WARN_EMPTY_BODY = YES 42 | CLANG_WARN_BOOL_CONVERSION = YES 43 | CLANG_WARN_CONSTANT_CONVERSION = YES 44 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES 45 | CLANG_WARN_ENUM_CONVERSION = YES 46 | CLANG_WARN_INT_CONVERSION = YES 47 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES 48 | CLANG_WARN_INFINITE_RECURSION = YES 49 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR 50 | CLANG_WARN_STRICT_PROTOTYPES = YES 51 | CLANG_WARN_COMMA = YES 52 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 53 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE 54 | CLANG_WARN_UNREACHABLE_CODE = YES 55 | GCC_WARN_UNUSED_FUNCTION = YES 56 | GCC_WARN_UNUSED_VARIABLE = YES 57 | 58 | // Apple LLVM 9.0 - Warnings - C++ 59 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES 60 | CLANG_WARN_SUSPICIOUS_MOVE = YES 61 | 62 | // Apple LLVM 9.0 - Warnings - Objective C 63 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR 64 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 65 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES 66 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES 67 | GCC_WARN_UNDECLARED_SELECTOR = YES 68 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR 69 | 70 | // Apple LLVM 9.0 - Warnings - Objective C and ARC 71 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 72 | 73 | // Static Analyzer - Generic Issuses 74 | CLANG_ANALYZER_NONNULL = YES 75 | 76 | // Static Analyzer - Issuses - Apple APIs 77 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE 78 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Shared.xcconfig" 2 | #include "Signing/DebugSigning.xcconfig" 3 | 4 | // Architectures 5 | ONLY_ACTIVE_ARCH = YES 6 | 7 | // Build Options 8 | DEBUG_INFORMATION_FORMAT = dwarf 9 | ENABLE_TESTABILITY = YES 10 | 11 | // Apple LLVM 9.0 - Code Generation 12 | GCC_OPTIMIZATION_LEVEL = 0 13 | 14 | // Apple LLVM 9.0 - Preprocessing 15 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited) 16 | 17 | // Swift Compiler - Code Generation 18 | SWIFT_OPTIMIZATION_LEVEL = -Onone 19 | 20 | // Swift Compiler - Custom Flags 21 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG 22 | 23 | // User-Defined 24 | MTL_ENABLE_DEBUG_INFO = YES 25 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/DebugTest.xcconfig: -------------------------------------------------------------------------------- 1 | #include "SharedTest.xcconfig" 2 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Shared.xcconfig" 2 | #include "Signing/ReleaseSigning.xcconfig" 3 | 4 | // Build Options 5 | DEBUG_INFORMATION_FORMAT = dwarf-with-dsym 6 | VALIDATE_PRODUCT = YES 7 | 8 | // Apple LLVM 9.0 - Preprocessing 9 | ENABLE_NS_ASSERTIONS = NO 10 | 11 | // Swift Compiler - Code Generation 12 | SWIFT_OPTIMIZATION_LEVEL = -Owholemodule 13 | SWIFT_COMPILATION_MODE = wholemodule 14 | 15 | // User-Defined 16 | MTL_ENABLE_DEBUG_INFO = NO 17 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/ReleaseTest.xcconfig: -------------------------------------------------------------------------------- 1 | #include "DebugTest.xcconfig" 2 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Shared.xcconfig: -------------------------------------------------------------------------------- 1 | // Deployment 2 | TARGETED_DEVICE_FAMILY = 1,2 3 | 4 | // Build Options 5 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = $(inherited) 6 | 7 | // Search Paths 8 | FRAMEWORK_SEARCH_PATHS = $(inherited) 9 | 10 | // Linking 11 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks 12 | 13 | // Packing 14 | INFOPLIST_FILE = iOSProject/Configurations/Info.plist 15 | PRODUCT_NAME = $(TARGET_NAME) 16 | 17 | // Asset Catalog Compiler - Options 18 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon 19 | 20 | // Swift Compiler - Language 21 | SWIFT_VERSION = 5.0 22 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/SharedTest.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Shared.xcconfig" 2 | 3 | // Build Options 4 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = $(inherited) YES 5 | 6 | // Linking 7 | BUNDLE_LOADER = $(TEST_HOST) 8 | LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks 9 | 10 | // Packaging 11 | INFOPLIST_FILE = iOSProjectTests/Configurations/Info.plist 12 | PRODUCT_BUNDLE_IDENTIFIER = com.messeb.ios.iosprojecttests 13 | PRODUCT_NAME = $(TARGET_NAME) 14 | 15 | // Swift Compiler - Code Generation 16 | SWIFT_OPTIMIZATION_LEVEL = -Onone 17 | 18 | // Signing 19 | CODE_SIGN_STYLE = Automatic 20 | 21 | // Testing 22 | TEST_HOST = $(BUILT_PRODUCTS_DIR)/iOSProject.app/iOSProject 23 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Signing/DebugSigning.xcconfig: -------------------------------------------------------------------------------- 1 | #include "SharedSigning.xcconfig" 2 | 3 | // Packing 4 | PRODUCT_BUNDLE_IDENTIFIER = com.example.iosproject.debug 5 | 6 | // Signing 7 | CODE_SIGN_STYLE = Automatic 8 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Signing/ReleaseSigning.xcconfig: -------------------------------------------------------------------------------- 1 | #include "SharedSigning.xcconfig" 2 | 3 | // Packing 4 | PRODUCT_BUNDLE_IDENTIFIER = com.example.iosproject 5 | 6 | // Signing 7 | CODE_SIGN_STYLE = Manual 8 | CODE_SIGN_IDENTITY = iPhone Distribution: Company (XXXXXXXXXX) 9 | PROVISIONING_PROFILE_SPECIFIER = iosproject-release-appstore 10 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Signing/SharedSigning.xcconfig: -------------------------------------------------------------------------------- 1 | // Signing 2 | DEVELOPMENT_TEAM = XXXXXXXXXX 3 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Signing/StagingSigning.xcconfig: -------------------------------------------------------------------------------- 1 | #include "SharedSigning.xcconfig" 2 | 3 | // Packing 4 | PRODUCT_BUNDLE_IDENTIFIER = com.example.iosproject.staging 5 | 6 | // Signing 7 | CODE_SIGN_STYLE = Manual 8 | CODE_SIGN_IDENTITY = iPhone Distribution: Company (XXXXXXXXXX) 9 | PROVISIONING_PROFILE_SPECIFIER = iosproject-staging-adhoc 10 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/Staging.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Release.xcconfig" 2 | #include "Signing/StagingSigning.xcconfig" 3 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Builds/StagingTest.xcconfig: -------------------------------------------------------------------------------- 1 | #include "DebugTest.xcconfig" 2 | -------------------------------------------------------------------------------- /iOSProject/Configurations/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "images" : [ 7 | { 8 | "filename" : "Icon-40.png", 9 | "size" : "40x40", 10 | "idiom" : "ipad", 11 | "scale" : "1x" 12 | }, 13 | { 14 | "filename" : "Icon-40@2x.png", 15 | "size" : "40x40", 16 | "idiom" : "ipad", 17 | "scale" : "2x" 18 | }, 19 | { 20 | "filename" : "Icon-60@2x.png", 21 | "size" : "60x60", 22 | "idiom" : "iphone", 23 | "scale" : "2x" 24 | }, 25 | { 26 | "filename" : "Icon-72.png", 27 | "size" : "72x72", 28 | "idiom" : "ipad", 29 | "scale" : "1x" 30 | }, 31 | { 32 | "filename" : "Icon-72@2x.png", 33 | "size" : "72x72", 34 | "idiom" : "ipad", 35 | "scale" : "2x" 36 | }, 37 | { 38 | "filename" : "Icon-76.png", 39 | "size" : "76x76", 40 | "idiom" : "ipad", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "filename" : "Icon-76@2x.png", 45 | "size" : "76x76", 46 | "idiom" : "ipad", 47 | "scale" : "2x" 48 | }, 49 | { 50 | "filename" : "Icon-Small-50.png", 51 | "size" : "50x50", 52 | "idiom" : "ipad", 53 | "scale" : "1x" 54 | }, 55 | { 56 | "filename" : "Icon-Small-50@2x.png", 57 | "size" : "50x50", 58 | "idiom" : "ipad", 59 | "scale" : "2x" 60 | }, 61 | { 62 | "filename" : "Icon-Small.png", 63 | "size" : "29x29", 64 | "idiom" : "iphone", 65 | "scale" : "1x" 66 | }, 67 | { 68 | "filename" : "Icon-Small@2x.png", 69 | "size" : "29x29", 70 | "idiom" : "iphone", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "filename" : "Icon.png", 75 | "size" : "57x57", 76 | "idiom" : "iphone", 77 | "scale" : "1x" 78 | }, 79 | { 80 | "filename" : "Icon@2x.png", 81 | "size" : "57x57", 82 | "idiom" : "iphone", 83 | "scale" : "2x" 84 | }, 85 | { 86 | "filename" : "Icon-Small@3x.png", 87 | "size" : "29x29", 88 | "idiom" : "iphone", 89 | "scale" : "3x" 90 | }, 91 | { 92 | "filename" : "Icon-40@3x.png", 93 | "size" : "40x40", 94 | "idiom" : "iphone", 95 | "scale" : "3x" 96 | }, 97 | { 98 | "filename" : "Icon-60@3x.png", 99 | "size" : "60x60", 100 | "idiom" : "iphone", 101 | "scale" : "3x" 102 | }, 103 | { 104 | "filename" : "Icon-40@2x.png", 105 | "size" : "40x40", 106 | "idiom" : "iphone", 107 | "scale" : "2x" 108 | }, 109 | { 110 | "filename" : "Icon-Small.png", 111 | "size" : "29x29", 112 | "idiom" : "ipad", 113 | "scale" : "1x" 114 | }, 115 | { 116 | "filename" : "Icon-Small@2x.png", 117 | "size" : "29x29", 118 | "idiom" : "ipad", 119 | "scale" : "2x" 120 | }, 121 | { 122 | "filename" : "Icon-83.5@2x.png", 123 | "size" : "83.5x83.5", 124 | "idiom" : "ipad", 125 | "scale" : "2x" 126 | }, 127 | { 128 | "filename" : "NotificationIcon@2x.png", 129 | "size" : "20x20", 130 | "idiom" : "iphone", 131 | "scale" : "2x" 132 | }, 133 | { 134 | "filename" : "NotificationIcon@3x.png", 135 | "size" : "20x20", 136 | "idiom" : "iphone", 137 | "scale" : "3x" 138 | }, 139 | { 140 | "filename" : "NotificationIcon~ipad.png", 141 | "size" : "20x20", 142 | "idiom" : "ipad", 143 | "scale" : "1x" 144 | }, 145 | { 146 | "filename" : "NotificationIcon~ipad@2x.png", 147 | "size" : "20x20", 148 | "idiom" : "ipad", 149 | "scale" : "2x" 150 | }, 151 | { 152 | "filename" : "ios-marketing.png", 153 | "size" : "1024x1024", 154 | "idiom" : "ios-marketing", 155 | "scale" : "1x" 156 | } 157 | ] 158 | } -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon@3x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon~ipad.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon~ipad@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/NotificationIcon~ipad@2x.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/ios-marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Resources/Assests.xcassets/AppIcon.appiconset/ios-marketing.png -------------------------------------------------------------------------------- /iOSProject/Resources/Assests.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } -------------------------------------------------------------------------------- /iOSProject/Resources/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 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /iOSProject/Scenes/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/iOSProject/Scenes/.gitignore -------------------------------------------------------------------------------- /iOSProject/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import UIKit 3 | 4 | /// Custom main.swift to prevent app execution in the unit test. 5 | /// Overwrites the app delegate with an empty implementation. 6 | 7 | private let argc = CommandLine.argc 8 | private let argv = UnsafeMutableRawPointer(CommandLine.unsafeArgv) 9 | .bindMemory( 10 | to: UnsafeMutablePointer?.self, 11 | capacity: Int(CommandLine.argc) 12 | ) 13 | 14 | // Could also be `nil` after the documentation 15 | private let principalClassName = NSStringFromClass(UIApplication.self) 16 | 17 | #if DEBUG 18 | extension ProcessInfo { 19 | 20 | private var isRunningTests: Bool { 21 | return arguments.contains("IS_RUNNING_TESTS") 22 | } 23 | 24 | /// Returns the proper app delegate type for the debug configuration 25 | public var appDelegateType: UIApplicationDelegate.Type { 26 | let appDelegateType: UIApplicationDelegate.Type = isRunningTests ? 27 | TestAppDelegate.self : 28 | AppDelegate.self 29 | return appDelegateType 30 | } 31 | } 32 | 33 | /// App delegate for the unit tests 34 | final class TestAppDelegate: UIResponder, UIApplicationDelegate { 35 | } 36 | 37 | private let delegateClassName = NSStringFromClass(ProcessInfo.processInfo.appDelegateType) 38 | #else 39 | private let delegateClassName = NSStringFromClass(AppDelegate.self) 40 | #endif 41 | 42 | _ = UIApplicationMain( 43 | argc, 44 | argv, 45 | principalClassName, 46 | delegateClassName 47 | ) 48 | -------------------------------------------------------------------------------- /iOSProjectTests/Configurations/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | -------------------------------------------------------------------------------- /iOSProjectTests/Tests/iOSProjectTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import iOSProject 3 | 4 | class ProjectTests: XCTestCase { 5 | 6 | override func setUp() { 7 | super.setUp() 8 | // Put setup code here. This method is called before the invocation of each test method in the class. 9 | } 10 | 11 | override func tearDown() { 12 | super.tearDown() 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | } 15 | 16 | func testExample() { 17 | // This is an example of a functional test case. 18 | // Use XCTAssert and related functions to verify your tests produce the correct results. 19 | } 20 | 21 | func testPerformanceExample() { 22 | // This is an example of a performance test case. 23 | self.measure { 24 | // Put the code you want to measure the time of here. 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /signing/.gitignore: -------------------------------------------------------------------------------- 1 | # Prevents check in unencrypted file 2 | *.mobileprovision 3 | *.p12 4 | *.cert 5 | -------------------------------------------------------------------------------- /signing/release/certificate.p12.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/signing/release/certificate.p12.enc -------------------------------------------------------------------------------- /signing/release/provisioning-profile.mobileprovision.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/signing/release/provisioning-profile.mobileprovision.enc -------------------------------------------------------------------------------- /signing/staging/certificate.p12.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/signing/staging/certificate.p12.enc -------------------------------------------------------------------------------- /signing/staging/provisioning-profile.mobileprovision.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/messeb/ios-project-template/967f0cd3e6bc877a32abcbf982067b94cb85c163/signing/staging/provisioning-profile.mobileprovision.enc --------------------------------------------------------------------------------