diff --git a/CHANGELOG.md b/CHANGELOG.md index 303ebbe..67a5b88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.0.1] - YYYY-MM-DD +- Include network utilities +- Adapt for SwiftUI +- Include Swift Package Manager + +## [0.0.1] - 2019-08-16 + +### Added + +- External libraries + - SwiftLint + - R.Swift + - SwiftDate + - IQKeyboardManager + - PromiseKit +- Internals + - Utilities + - Logging + - Localisation + - UserDefaults + +### Fixed + +- Errors in `project.yml` which lead to incorrect configured Xcode projects + +[unreleased]: https://github.com/alexanderwe/ios-starter/compare/v1.0.0...HEAD +[0.0.1]: https://github.com/alexanderwe/ios-starter/releases/tag/v0.0.1 + + diff --git a/README.md b/README.md index 4a0a589..385f8d9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ # iOS-Starter -This is a template project for boostrapping iOS applications. +![version](https://img.shields.io/badge/version-v0.0.1-green) + +This is a template project for bootstrapping iOS applications. + +> When Xcode 11 is released, this template will convert from CocoaPods to Swift Package Manager ## Prequisites @@ -17,14 +21,33 @@ brew install xcodegen - `cookiecutter` will prompt you for: - The project name - Apple Developer Team details - - etc. + - other details - `cookiecutter` will create all necessary files -- `XcodeGen` will now run automatically creating a `.xcodeproj` file +- `XcodeGen` runs and automatically creates a `.xcodeproj` file - Afterwards `pod install` will run to download all necessary dependencies - Finally `Xcode` will launch your new project - Happy Coding !ย ๐Ÿค“ -## Included libraries +## Included external libraries + +- Handle asynchronous code +- [PromiseKit](https://github.com/mxcl/PromiseKit) - Avoid the Callback Hell +- Code Style + - [SwiftLint](https://www.github.com/realm/SwiftLint) - Common linting rules +- Helpers + - [Rswift](https://github.com/mac-cain13/R.swift) - Type safe access to string resources + - [SwiftDate](https://github.com/malcommac/SwiftDate) - Work with Dates is a breeze + - [IQKeyboardManager](https://github.com/hackiftekhar/IQKeyboardManager) - Handle common keyboard issues on iOS + +## Structure + +The structure of the project tries to follow the idea in [this article](https://theswiftdev.com/2016/07/06/conventions-for-xcode/) from `The.Swift.Dev` + +## Git Hooks + +This template comes with a `.githooks` directory. Inside you can find and create hooks which will run in the local `.git` repository. + +Available hooks: -- [SwfitLint](https://www.github.com/realm/SwiftLint) - Common linting rules -- [Rswft](https://github.com/mac-cain13/R.swift) - Type safe access to string resources +- commit-msg (run before committing): + - Verifies that the commit message follows the standard [Conventional Commits](https://www.conventionalcommits.org) specification (+ one additional commit type `ci`) diff --git a/cookiecutter.json b/cookiecutter.json index d4c006e..fffe797 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -1,11 +1,11 @@ { "projectName": "Example", "projectDirectory": "{{cookiecutter.projectName|lower|replace(' ', '-')}}-ios", - "teamId": "123456", - "teamName": "Your Team Name", - "companyName": "Your company name", + "teamId": "TeamID", + "teamName": "TeamName", + "companyName": "CompanyName", "bundleIdentifier": "com.example.{{cookiecutter.projectName|lower|replace(' ', '-')}}", - "deploymentTarget": "12.0", + "deploymentTarget": "12.4", "runCocoaPods": "y", "runXcodeGen": "y" } diff --git a/hooks/post_gen_project.sh b/hooks/post_gen_project.sh index 747ce0f..c26a70f 100644 --- a/hooks/post_gen_project.sh +++ b/hooks/post_gen_project.sh @@ -1,20 +1,26 @@ #! /bin/bash +# Run xcodegen to create .xcodeproj file {%- if cookiecutter.runXcodeGen == 'y' %} xcodegen {%- endif %} +# Install cocoapods dependecies {%- if cookiecutter.runCocoaPods == 'y' %} pod install {%- endif %} - +# If xcodegen has generated a .xcodeproj file we want to open it {%- if cookiecutter.runXcodeGen == 'y' %} xed . {%- endif %} + +# Set up git git init -mv commit-msg .git/hooks/commit-msg -chmod u+x .git/hooks/commit-msg + +## Configure git hooks +chmod +x ./.githooks/commit-msg +git config core.hooksPath .githooks printf 'all done - enjoy ๐Ÿค“' \ No newline at end of file diff --git a/{{cookiecutter.projectDirectory}}/.githooks/commit-msg b/{{cookiecutter.projectDirectory}}/.githooks/commit-msg new file mode 100644 index 0000000..942c30b --- /dev/null +++ b/{{cookiecutter.projectDirectory}}/.githooks/commit-msg @@ -0,0 +1,8 @@ +#!/bin/sh + +# Directory of the hooks +hookDir=$(dirname $0) + +# Specify the hooks you want to run during +# the commit-msg process: +$hookDir/verify_conventional_commit "$1" \ No newline at end of file diff --git a/{{cookiecutter.projectDirectory}}/commit-msg b/{{cookiecutter.projectDirectory}}/.githooks/verify_conventional_commit similarity index 64% rename from {{cookiecutter.projectDirectory}}/commit-msg rename to {{cookiecutter.projectDirectory}}/.githooks/verify_conventional_commit index 34a9c05..7e72783 100755 --- a/{{cookiecutter.projectDirectory}}/commit-msg +++ b/{{cookiecutter.projectDirectory}}/.githooks/verify_conventional_commit @@ -5,13 +5,15 @@ def main(): # example: # feat(apikey): added the ability to add api key to configuration try: - pattern = r'(build|ci|docs|feat|fix|perf|refactor|style|test|chore|revert)(\([\w\-]+\))?:\s.*' + pattern = r'(fix|feat|chore|docs|style|refactor|perf|test|ci)(\([\w\-]+\))?:\s.*' + filename = sys.argv[1] + ss = open(filename, 'r').read() m = re.match(pattern, ss) if m == None: - raise Exception("conventional commit validation failed") + raise Exception("conventional commit validation failed") except Exception as e: print(e) - exit(1) + exit(1) if __name__ == "__main__": main() diff --git a/{{cookiecutter.projectDirectory}}/.swiftlint.yml b/{{cookiecutter.projectDirectory}}/.swiftlint.yml index ed1c65b..a7c81fc 100644 --- a/{{cookiecutter.projectDirectory}}/.swiftlint.yml +++ b/{{cookiecutter.projectDirectory}}/.swiftlint.yml @@ -1,5 +1,3 @@ -# Based on https://github.com/Lickability/swift-best-practices/blob/master/.swiftlint.yml - disabled_rules: # rule identifiers to exclude from running # Rationale: Xcode auto indentation can cause this warning # https://github.com/realm/SwiftLint/blob/master/Rules.md#closure-end-indentation diff --git a/{{cookiecutter.projectDirectory}}/Podfile b/{{cookiecutter.projectDirectory}}/Podfile index 7606ffb..755264f 100644 --- a/{{cookiecutter.projectDirectory}}/Podfile +++ b/{{cookiecutter.projectDirectory}}/Podfile @@ -1,24 +1,29 @@ # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' -target '{{cookiecutter.projectName}}' do +target 'iOS Application' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! - # Pods for {{cookiecutter.projectName}} + # Pods for iOS Application + + # Async + pod 'PromiseKit' # Code Quality pod 'SwiftLint' # Helpers pod 'R.swift' + pod 'IQKeyboardManagerSwift' + pod 'SwiftDate' - target '{{cookiecutter.projectName}}Tests' do + target 'iOS Application Tests' do inherit! :search_paths # Pods for testing end - target '{{cookiecutter.projectName}}UITests' do + target 'iOS Application UI Tests' do inherit! :search_paths # Pods for testing end diff --git a/{{cookiecutter.projectDirectory}}/README.md b/{{cookiecutter.projectDirectory}}/README.md index a8b16f0..a420a4c 100644 --- a/{{cookiecutter.projectDirectory}}/README.md +++ b/{{cookiecutter.projectDirectory}}/README.md @@ -3,7 +3,8 @@ ## Setup - Fill the README -- Move `R.generated.swift` to `Sources` and untick `Copy items if needed` +- Initially build the project +- Add `R.generated.swift` from `Sources` to the project and untick `Copy items if needed` - Delete this TODO section. (And enjoy your fresh and clean Project-setup ๐Ÿ™Œ) --- diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}Tests/Info.plist b/{{cookiecutter.projectDirectory}}/iOS Application Tests/Info.plist similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}Tests/Info.plist rename to {{cookiecutter.projectDirectory}}/iOS Application Tests/Info.plist diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}Tests/{{cookiecutter.projectName}}Tests.swift b/{{cookiecutter.projectDirectory}}/iOS Application Tests/{{cookiecutter.projectName}}Tests.swift similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}Tests/{{cookiecutter.projectName}}Tests.swift rename to {{cookiecutter.projectDirectory}}/iOS Application Tests/{{cookiecutter.projectName}}Tests.swift diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}UITests/Info.plist b/{{cookiecutter.projectDirectory}}/iOS Application UI Tests/Info.plist similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}UITests/Info.plist rename to {{cookiecutter.projectDirectory}}/iOS Application UI Tests/Info.plist diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}UITests/{{cookiecutter.projectName}}UITests.swift b/{{cookiecutter.projectDirectory}}/iOS Application UI Tests/{{cookiecutter.projectName}}UITests.swift similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}UITests/{{cookiecutter.projectName}}UITests.swift rename to {{cookiecutter.projectDirectory}}/iOS Application UI Tests/{{cookiecutter.projectName}}UITests.swift diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Assets.xcassets/AppIcon.appiconset/Contents.json b/{{cookiecutter.projectDirectory}}/iOS Application/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Assets.xcassets/AppIcon.appiconset/Contents.json rename to {{cookiecutter.projectDirectory}}/iOS Application/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Assets.xcassets/Contents.json b/{{cookiecutter.projectDirectory}}/iOS Application/Assets.xcassets/Contents.json similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Assets.xcassets/Contents.json rename to {{cookiecutter.projectDirectory}}/iOS Application/Assets.xcassets/Contents.json diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/AppDelegate.swift b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/AppDelegate.swift similarity index 90% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/AppDelegate.swift rename to {{cookiecutter.projectDirectory}}/iOS Application/Sources/AppDelegate.swift index 94cd769..665004f 100644 --- a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/AppDelegate.swift +++ b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/AppDelegate.swift @@ -7,6 +7,7 @@ // import UIKit +import IQKeyboardManagerSwift @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -15,6 +16,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. + + // Init IQKeyboardManager + // IQKeyboardManager.shared.enable = true + // IQKeyboardManager.shared.shouldResignOnTouchOutside = true + // IQKeyboardManager.shared.enableAutoToolbar = false + return true } diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Base.lproj/Main.storyboard b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Base.lproj/Main.storyboard similarity index 51% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Base.lproj/Main.storyboard rename to {{cookiecutter.projectDirectory}}/iOS Application/Sources/Base.lproj/Main.storyboard index f1bcf38..68520e8 100644 --- a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Base.lproj/Main.storyboard +++ b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Base.lproj/Main.storyboard @@ -1,7 +1,10 @@ - + + + + - + @@ -11,9 +14,21 @@ - + + + + + + + + diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Extensions/.gitkeep b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Extensions/.gitkeep similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Extensions/.gitkeep rename to {{cookiecutter.projectDirectory}}/iOS Application/Sources/Extensions/.gitkeep diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/Localization/Localization.swift b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/Localization/Localization.swift similarity index 87% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/Localization/Localization.swift rename to {{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/Localization/Localization.swift index 8c11c54..75613b8 100644 --- a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/Localization/Localization.swift +++ b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/Localization/Localization.swift @@ -1,6 +1,6 @@ // -// Loca.swift -// PTV +// Localization.swift +// {{cookiecutter.projectName}} // // Created by Automated on {% now 'utc', '%d/%m/%Y' %}. // Copyright ยฉ {% now 'utc', '%Y' %} {{cookiecutter.companyName}}. All rights reserved. diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/Logging/Logging.swift b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/Logging/Logging.swift similarity index 99% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/Logging/Logging.swift rename to {{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/Logging/Logging.swift index 61c81b2..72f26e8 100644 --- a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/Logging/Logging.swift +++ b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/Logging/Logging.swift @@ -15,11 +15,11 @@ extension OSLogType: CustomStringConvertible { case OSLogType.info: return "โ„น๏ธ(info)" case OSLogType.debug: - return "๐Ÿ”น(debug)" + return "๐Ÿ›(debug)" case OSLogType.error: return "โ€ผ๏ธ(error)" case OSLogType.fault: - return "๐Ÿ’ฃ(fault)" + return "๐Ÿงจ(fault)" default: return "DEFAULT" } diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/UserDefaults/UserDefaults.swift b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/UserDefaults/UserDefaults.swift similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/Helpers/UserDefaults/UserDefaults.swift rename to {{cookiecutter.projectDirectory}}/iOS Application/Sources/Helpers/UserDefaults/UserDefaults.swift diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/ViewController.swift b/{{cookiecutter.projectDirectory}}/iOS Application/Sources/ViewController.swift similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/Sources/ViewController.swift rename to {{cookiecutter.projectDirectory}}/iOS Application/Sources/ViewController.swift diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/SupportingFiles/Base.lproj/LaunchScreen.storyboard b/{{cookiecutter.projectDirectory}}/iOS Application/SupportingFiles/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/SupportingFiles/Base.lproj/LaunchScreen.storyboard rename to {{cookiecutter.projectDirectory}}/iOS Application/SupportingFiles/Base.lproj/LaunchScreen.storyboard diff --git a/{{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/SupportingFiles/Info.plist b/{{cookiecutter.projectDirectory}}/iOS Application/SupportingFiles/Info.plist similarity index 100% rename from {{cookiecutter.projectDirectory}}/{{cookiecutter.projectName}}/SupportingFiles/Info.plist rename to {{cookiecutter.projectDirectory}}/iOS Application/SupportingFiles/Info.plist diff --git a/{{cookiecutter.projectDirectory}}/project.yml b/{{cookiecutter.projectDirectory}}/project.yml index 1248d94..37de314 100644 --- a/{{cookiecutter.projectDirectory}}/project.yml +++ b/{{cookiecutter.projectDirectory}}/project.yml @@ -1,96 +1,68 @@ name: {{cookiecutter.projectName}} options: - xcodeVersion: 10.3 + xcodeVersion: 10.4 minimumXcodeGenVersion: 2.6.0 -configs: - Debug-live: debug - Debug-dev: debug - Debug-staging: debug - Release-live: release - Release-dev: release - Release-staging: release settings: base: DEVELOPMENT_TEAM: {{cookiecutter.teamId}} - SWIFT_VERSION: "5.0" -attributes: - ORGANIZATIONNAME: {{cookiecutter.teamName}} + SWIFT_VERSION: "5.0" targets: - {{cookiecutter.projectName}}: + iOS Application: type: application platform: iOS - deploymentTarget: "{{cookiecutter.deploymentTarget}}" - scheme: - configVariants: - - live - - dev - - staging + deploymentTarget: {{cookiecutter.deploymentTarget}} + scheme: {} settings: base: - PRODUCT_BUNDLE_IDENTIFIER: {{cookiecutter.bundleIdentifier}}$(BUILD_VERION_SUFFIX) - configs: - Debug-live: - BUILD_VERION_SUFFIX: "" - Debug-dev: - BUILD_VERION_SUFFIX: "-dev" - Debug-staging: - BUILD_VERION_SUFFIX: "-staging" - Release-live: - BUILD_VERION_SUFFIX: "" - SWIFT_COMPILATION_MODE: wholemodule - Release-dev: - BUILD_VERION_SUFFIX: "-dev" - SWIFT_COMPILATION_MODE: wholemodule - Release-staging: - BUILD_VERION_SUFFIX: "-staging" - SWIFT_COMPILATION_MODE: wholemodule + PRODUCT_BUNDLE_IDENTIFIER: {{cookiecutter.bundleIdentifier}} info: - path: {{cookiecutter.projectName}}/SupportingFiles/Info.plist + path: iOS Application/SupportingFiles/Info.plist properties: - CFBundleDisplayName: {{cookiecutter.projectName}}$(BUILD_VERION_SUFFIX) + CFBundleDisplayName: {{cookiecutter.projectName}} UISupportedInterfaceOrientations: - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UIRequiresFullScreen: YES UILaunchStoryboardName: LaunchScreen + UIMainStoryboardFile: Main UIRequiredDeviceCapabilities: [armv7] ITSAppUsesNonExemptEncryption: NO LSRequiresIPhoneOS: YES - _Configuration: $(CONFIGURATION) - sources: - - {{cookiecutter.projectName}} + _Configuration: $(CONFIGURATION) + sources: + - iOS Application/ preBuildScripts: - script: | - "$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/{{cookiecutter.projectName}}/Sources/R.generated.swift" + "$PODS_ROOT/R.swift/rswift" generate "$SRCROOT/iOS Application/Sources/R.generated.swift" name: R.Swift generate inputFiles: - $(TEMP_DIR)/rswift-lastrun outputFiles: - - $(SRCROOT)/{{cookiecutter.projectName}}/Sources/R.generated.swift + - $(SRCROOT)/iOS Application/Sources/R.generated.swift postCompileScripts: - script: | ${PODS_ROOT}/SwiftLint/swiftlint - name: SwiftLint - {{cookiecutter.projectName}}Tests: + name: SwiftLint + iOS Application Tests: platform: iOS type: bundle.unit-test sources: - - {{cookiecutter.projectName}}Tests/ + - iOS Application Tests/ dependencies: - - target: {{cookiecutter.projectName}} + - target: iOS Application scheme: testTargets: - - {{cookiecutter.projectName}}Tests + - iOS Application Tests gatherCoverageData: true - {{cookiecutter.projectName}}UITests: + iOS Application UI Tests: platform: iOS type: bundle.ui-testing sources: - - {{cookiecutter.projectName}}UITests/ + - iOS Application UI Tests/ dependencies: - - target: {{cookiecutter.projectName}} + - target: iOS Application scheme: testTargets: - - {{cookiecutter.projectName}}UITests - gatherCoverageData: true \ No newline at end of file + - iOS Application UI Tests + gatherCoverageData: true \ No newline at end of file