5. Oct 2021iOS

Xcode project Templates Vol. 3: How to automate the configuration of swiftlint and swiftgen

As the title implies, in this article I'll show you how to add run scripts and ready-made swiftlint and swiftgen configuration to your project via a project template.

Andrej JaššoiOS Developer

In this tutorial I will show you how to add build scripts to a project via a project template. Scripts in projects usually look very inconsistent depending on the number of people setting up projects. However, if you always use the same template there is nowhere to go wrong. This is what our template looked like in the previous article about Xcode Templates.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>Kind</key>
 <string>Xcode.Xcode3.ProjectTemplateUnitKind</string>
 <key>Identifier</key>
 <string>com.goodrequest.singleViewApplication</string>
 <key>Ancestors</key>
 <array>
	 <string>com.apple.dt.unit.applicationBase</string>
	  <string>com.apple.dt.unit.iosBase</string>
    <string>com.goodrequest.CocoaPods</string> <!--ID of the Pod template-->
	</array>
 <key>Concrete</key>
 <true/>
 <key>Definitions</key>
 <dict>
   <key>Helpers/TypeAliases.swift</key>
   <dict>
     <key>Path</key>
     <string>Helpers/TypeAliases.swift</string>
     <key>Group</key>
     <string>Helpers</string>
   </dict>
  <key>Application/AppDelegate.swift</key>
  <dict>
   <key>Path</key>
   <string>Application/AppDelegate.swift</string>
   <key>Group</key>
   <array>
    <string>Application</string>
   </array>
  </dict>
  <key>Models/Response/SampleResponse.swift</key>
  <dict>
   <key>Path</key>
   <string>Models/Response/SampleResponse.swift</string>
   <key>Group</key>
   <array>
    <string>Models</string>
    <string>Response</string>
   </array>
  </dict>
  <key>Models/Request/SampleRequest.swift</key>
  <dict>
   <key>Path</key>
   <string>Models/Request/SampleRequest.swift</string>
   <key>Group</key>
   <array>
    <string>Models</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Dependency/DependencyContainer.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Dependency/DependencyContainer.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Dependency</string>
   </array>
  </dict>
  <key>Managers/Request/RequestManager.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/RequestManager.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Request/RequestManagerType.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/RequestManagerType.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Request/Endpoint.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/Endpoint.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Coordinators/Coordinator.swift</key>
  <dict>
   <key>Path</key>
   <string>Coordinators/Coordinator.swift</string>
   <key>Group</key>
   <string>Coordinators</string>
  </dict>
  <key>Coordinators/AppCoordinator.swift</key>
  <dict>
   <key>Path</key>
   <string>Coordinators/AppCoordinator.swift</string>
   <key>Group</key>
   <string>Coordinators</string>
  </dict>
  <key>Screens/SampleController/SampleViewController.swift</key>
  <dict>
   <key>Path</key>
  <string>Screens/SampleController/SampleViewController.swift</string>
   <key>Group</key>
   <array>
    <string>Screens</string>
    <string>SampleController</string>
   </array>
  </dict>
  <key>Views/SampleView/SampleView.swift</key>
  <dict>
   <key>Path</key>
   <string>Views/SampleView/SampleView.swift</string>
   <key>Group</key>
   <array>
    <string>Views</string>
    <string>SampleView</string>
   </array>
  </dict>
  <key>Resources/Assets.xcassets</key>
  <dict>
   <key>Path</key>
   <string>Resources/Assets.xcassets</string>
   <key>Group</key>
   <array>
    <string>Resources</string>
   </array>
  </dict>
  <key>Resources/Colors.xcassets</key>
  <dict>
   <key>Path</key>
   <string>Resources/Colors.xcassets</string>
   <key>Group</key>
   <array>
    <string>Resources</string>
   </array>
  </dict>
 </dict>
 <key>Nodes</key>
 <array>
  <string>Application/AppDelegate.swift</string>
  <string>Models/Response/SampleResponse.swift</string>
  <string>Models/Request/SampleRequest.swift</string>
  <string>Helpers/TypeAliases.swift</string>
  <string>Managers/Dependency/DependencyContainer.swift</string>
  <string>Managers/Request/RequestManager.swift</string>
  <string>Managers/Request/RequestManagerType.swift</string>
  <string>Managers/Request/Endpoint.swift</string>
  <string>Coordinators/Coordinator.swift</string>
  <string>Coordinators/AppCoordinator.swift</string>
  <string>Screens/SampleController/SampleViewController.swift</string>
  <string>Views/SampleView/SampleView.swift</string>
  <string>Resources/Colors.xcassets</string>
  <string>Resources/Assets.xcassets</string>
 </array>
 <key>Project</key>
 <dict>
     <key>SharedSettings</key>
     <dict>
         <key>SWIFT_VERSION</key>
         <string>5.0</string>
     </dict>
 </dict>
 </dict>
</plist>

You may have noticed that I added a new section, which you can see below ⬇️

<key>Project</key>
 <dict>
     <key>SharedSettings</key>
     <dict>
         <key>SWIFT_VERSION</key>
         <string>5.0</string>
     </dict>
 </dict>

This is due to the new Xcode 13. However, today we will add a brand new Targets section to the template.

<key>Targets</key>
	<array>
		<dict>
			<key>TargetIdentifier</key>
			<string>com.apple.dt.cocoaTouchApplicationTarget</string>
			<key>BuildPhases</key>
			<array>
				<dict>
					<key>Name</key>
					<string>🛠 Generate enums with SwiftGen</string>
					<key>SortOrder</key>
					<string>1</string>
					<key>Class</key>
					<string>ShellScript</string>
					<key>ShellPath</key>
					<string>/bin/sh</string>
					<key>ShellScript</key>
					<string>SWIFT_GEN="${PODS_ROOT}/SwiftGen/bin/swiftgen"
SWIFT_GEN_CONFIG="${PROJECT_DIR}/${PROJECT_NAME}/Resources/SwiftGen/swiftgen.yml"

if test -f "${SWIFT_GEN}"; then
    if test -f "${SWIFT_GEN_CONFIG}"; then
        "${SWIFT_GEN}" config run --verbose --config "${SWIFT_GEN_CONFIG}"
    else
        echo "warning: Swifgen configuration file missing make sure the path "$SWIFT_GEN_CONFIG" contains the file 😭😩🤦‍♂️"
    fi
else
    echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen 😭😩🤦‍♂️"
fi</string>
				</dict>
				<dict>
					<key>Name</key>
					<string>🧹 Validate codestyle with SwiftLint</string>
					<key>SortOrder</key>
					<string>1</string>
					<key>Class</key>
					<string>ShellScript</string>
					<key>ShellPath</key>
					<string>/bin/sh</string>
					<key>ShellScript</key>
					<string>SWIFT_LINT="${PODS_ROOT}/SwiftLint/swiftlint"
 SWIFT_LINT_CONFIG="${SRCROOT}/${PROJECT_NAME}/Resources/.swiftlint.yml"

if test -f "${SWIFT_LINT}"; then
    if test -f "${SWIFT_LINT_CONFIG}"; then
        "${SWIFT_LINT}" --config "${SWIFT_LINT_CONFIG}"
    else
        echo "warning: Swiflint configuration file missing make your the submodule is fetched 😭😩🤦‍♂️"
    fi
else
    echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint 😭😩🤦‍♂️"
fi</string>
				</dict>
			</array>
		</dict>
	</array>

The Targets key specifies a list of project targets, but we will only use one in specific, the default main target of the application we are creating. To do this, you need to specify a target ID, which is:

com.apple.dt.cocoaTouchApplicationTarget

Then we enter the build phases key, which is again a list from the buildphases tab of the project.

Enter a name for the script in the Name variable. You can also be little creative with the name and enter various emoji, which will immediately guide you visually to the script.

  • SortOrder determines the order of the scripts.
  • Class must be with standard ShellScript sh scripts.
  • ShellPath by default also /bin/sh
  • ShellScript launches the library and specifies the path to the configuration file.

Within scripts, SWIFT_LINT_CONFIG specifies the path to the configuration file, as well as ANY_LINT_CONFIG and SWIFT_GEN_CONFIG.

Swiftgen localizations should be set only after selecting the localization and the base language of the app. But the probable setup is still listed in the template.

#strings:
#    inputs: ${PROJECT_DIR}/${PROJECT_NAME}/Resources/en.lproj/Localizable.strings
#    outputs:
#        - templateName: structured-swift5
#          output: ${PROJECT_DIR}/${PROJECT_NAME}/Resources/SwiftGen/Localizable.swift
#          params:
#            enumName: L
xcassets:
  - inputs: ${PROJECT_DIR}/${PROJECT_NAME}/Resources/Assets.xcassets
    outputs:
      - templateName: swift5
        output: ${PROJECT_DIR}/${PROJECT_NAME}/Resources/SwiftGen/Assets.swift
        params:
          enumName: Asset
  - inputs: ${PROJECT_DIR}/${PROJECT_NAME}/Resources/Colors.xcassets
    outputs:
      - templateName: swift5
        output: ${PROJECT_DIR}/${PROJECT_NAME}/Resources/SwiftGen/Colors.swift
        params:
          enumName: Color

You can write Swiftlint by yourself, but even if you do not enter anything in the configuration file, swiftlint will take the default configuration.

Then we add the swiftgen files and the swiflint configuration file to the nodes:

 <string>Resources/Localizable.strings</string>
  <string>Resources/SwiftGen/Assets.swift</string>
  <string>Resources/SwiftGen/Colors.swift</string>
  <string>Resources/SwiftGen/Localizable.swift</string>
  <string>Resources/.swiftlint.yml</string>

We will add to the definitions:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>Kind</key>
 <string>Xcode.Xcode3.ProjectTemplateUnitKind</string>
 <key>Identifier</key>
 <string>com.goodrequest.singleViewApplication</string>
 <key>Ancestors</key>
 <array>
	 <string>com.apple.dt.unit.applicationBase</string>
	  <string>com.apple.dt.unit.iosBase</string>
    <string>com.goodrequest.CocoaPods</string> <!--ID of the Pod template-->
	</array>
 <key>Concrete</key>
 <true/>
 <key>Definitions</key>
 <dict>
  <key>Application/AppDelegate.swift</key>
  <dict>
   <key>Path</key>
   <string>Application/AppDelegate.swift</string>
   <key>Group</key>
   <array>
    <string>Application</string>
   </array>
  </dict>
  <key>Models/Response/SampleResponse.swift</key>
  <dict>
   <key>Path</key>
   <string>Models/Response/SampleResponse.swift</string>
   <key>Group</key>
   <array>
    <string>Models</string>
    <string>Response</string>
   </array>
  </dict>
  <key>Models/Request/SampleRequest.swift</key>
  <dict>
   <key>Path</key>
   <string>Models/Request/SampleRequest.swift</string>
   <key>Group</key>
   <array>
    <string>Models</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Dependency/DependencyContainer.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Dependency/DependencyContainer.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Dependency</string>
   </array>
  </dict>
  <key>Managers/Request/RequestManager.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/RequestManager.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Request/RequestManagerType.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/RequestManagerType.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Request/Endpoint.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/Endpoint.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Coordinators/Coordinator.swift</key>
  <dict>
   <key>Path</key>
   <string>Coordinators/Coordinator.swift</string>
   <key>Group</key>
   <string>Coordinators</string>
  </dict>
  <key>Coordinators/AppCoordinator.swift</key>
  <dict>
   <key>Path</key>
   <string>Coordinators/AppCoordinator.swift</string>
   <key>Group</key>
   <string>Coordinators</string>
  </dict>
  <key>Screens/SampleController/SampleViewController.swift</key>
  <dict>
   <key>Path</key>
  <string>Screens/SampleController/SampleViewController.swift</string>
   <key>Group</key>
   <array>
    <string>Screens</string>
    <string>SampleController</string>
   </array>
  </dict>
  <key>Views/SampleView/SampleView.swift</key>
  <dict>
   <key>Path</key>
   <string>Views/SampleView/SampleView.swift</string>
   <key>Group</key>
   <array>
    <string>Views</string>
    <string>SampleView</string>
   </array>
  </dict>
  <key>Resources/Assets.xcassets</key>
  <dict>
   <key>Path</key>
   <string>Resources/Assets.xcassets</string>
   <key>Group</key>
   <array>
    <string>Resources</string>
   </array>
  </dict>
  <key>Resources/Colors.xcassets</key>
  <dict>
   <key>Path</key>
   <string>Resources/Colors.xcassets</string>
   <key>Group</key>
   <array>
    <string>Resources</string>
   </array>
  </dict>
  <key>Resources/SwiftGen/swiftgen.yml</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/swiftgen.yml</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Resources/SwiftGen/Colors.swift</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/Colors.swift</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Resources/SwiftGen/Assets.swift</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/Assets.swift</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Resources/SwiftGen/Localizable.swift</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/Localizable.swift</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Helpers/TypeAliases.swift</key>
  <dict>
    <key>Path</key>
    <string>Helpers/TypeAliases.swift</string>
    <key>Group</key>
    <string>Helpers</string>
  </dict>
  <key>Resources/.swiftlint.yml</key>
  <dict>
    <key>Path</key>
    <string>Resources/.swiftlint.yml</string>
    <key>Group</key>
    <string>Resources</string>
  </dict>
 </dict>
 <key>Nodes</key>
 <array>
  <string>Helpers/TypeAliases.swift</string>
  <string>Application/AppDelegate.swift</string>
  <string>Models/Response/SampleResponse.swift</string>
  <string>Models/Request/SampleRequest.swift</string>
  <string>Managers/Dependency/DependencyContainer.swift</string>
  <string>Managers/Request/RequestManager.swift</string>
  <string>Managers/Request/RequestManagerType.swift</string>
  <string>Managers/Request/Endpoint.swift</string>
  <string>Coordinators/Coordinator.swift</string>
  <string>Coordinators/AppCoordinator.swift</string>
  <string>Screens/SampleController/SampleViewController.swift</string>
  <string>Views/SampleView/SampleView.swift</string>
  <string>Resources/Colors.xcassets</string>
  <string>Resources/Assets.xcassets</string>
  <string>Resources/SwiftGen/swiftgen.yml</string>
  <string>Resources/Colors.xcassets</string>
  <string>Resources/Assets.xcassets</string>
  <string>Resources/Localizable.strings</string>
  <string>Resources/SwiftGen/Assets.swift</string>
  <string>Resources/SwiftGen/Colors.swift</string>
  <string>Resources/SwiftGen/Localizable.swift</string>
  <string>Resources/.swiftlint.yml</string>
 </array>
 <key>Targets</key>
	<array>
		<dict>
			<key>TargetIdentifier</key>
			<string>com.apple.dt.cocoaTouchApplicationTarget</string>
			<key>BuildPhases</key>
			<array>
				<dict>
					<key>Name</key>
					<string>🛠 Generate enums with SwiftGen</string>
					<key>SortOrder</key>
					<string>1</string>
					<key>Class</key>
					<string>ShellScript</string>
					<key>ShellPath</key>
					<string>/bin/sh</string>
					<key>ShellScript</key>
					<string>SWIFT_GEN="${PODS_ROOT}/SwiftGen/bin/swiftgen"
SWIFT_GEN_CONFIG="${PROJECT_DIR}/${PROJECT_NAME}/Resources/SwiftGen/swiftgen.yml"

if test -f "${SWIFT_GEN}"; then
    if test -f "${SWIFT_GEN_CONFIG}"; then
        "${SWIFT_GEN}" config run --verbose --config "${SWIFT_GEN_CONFIG}"
    else
        echo "warning: Swifgen configuration file missing make sure the path "$SWIFT_GEN_CONFIG" contains the file 😭😩🤦‍♂️"
    fi
else
    echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen 😭😩🤦‍♂️"
fi</string>
				</dict>
				<dict>
					<key>Name</key>
					<string>🧹 Validate codestyle with SwiftLint</string>
					<key>SortOrder</key>
					<string>1</string>
					<key>Class</key>
					<string>ShellScript</string>
					<key>ShellPath</key>
					<string>/bin/sh</string>
					<key>ShellScript</key>
					<string>SWIFT_LINT="${PODS_ROOT}/SwiftLint/swiftlint"
 SWIFT_LINT_CONFIG="${SRCROOT}/${PROJECT_NAME}/Resources/.swiftlint.yml"

if test -f "${SWIFT_LINT}"; then
    if test -f "${SWIFT_LINT_CONFIG}"; then
        "${SWIFT_LINT}" --config "${SWIFT_LINT_CONFIG}"
    else
        echo "warning: Swiflint configuration file missing make your the submodule is fetched 😭😩🤦‍♂️"
    fi
else
    echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint 😭😩🤦‍♂️"
fi</string>
				</dict>
			</array>
		</dict>
	</array>
  <key>Project</key>
	<dict>
			<key>SharedSettings</key>
			<dict>
					<key>SWIFT_VERSION</key>
					<string>5.0</string>
			</dict>
	</dict>
 </dict>
</plist>

The result looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>Kind</key>
 <string>Xcode.Xcode3.ProjectTemplateUnitKind</string>
 <key>Identifier</key>
 <string>com.goodrequest.singleViewApplication</string>
 <key>Ancestors</key>
 <array>
	 <string>com.apple.dt.unit.applicationBase</string>
	  <string>com.apple.dt.unit.iosBase</string>
    <string>com.goodrequest.CocoaPods</string> <!--ID of the Pod template-->
	</array>
 <key>Concrete</key>
 <true/>
 <key>Definitions</key>
 <dict>
  <key>Application/AppDelegate.swift</key>
  <dict>
   <key>Path</key>
   <string>Application/AppDelegate.swift</string>
   <key>Group</key>
   <array>
    <string>Application</string>
   </array>
  </dict>
  <key>Models/Response/SampleResponse.swift</key>
  <dict>
   <key>Path</key>
   <string>Models/Response/SampleResponse.swift</string>
   <key>Group</key>
   <array>
    <string>Models</string>
    <string>Response</string>
   </array>
  </dict>
  <key>Models/Request/SampleRequest.swift</key>
  <dict>
   <key>Path</key>
   <string>Models/Request/SampleRequest.swift</string>
   <key>Group</key>
   <array>
    <string>Models</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Dependency/DependencyContainer.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Dependency/DependencyContainer.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Dependency</string>
   </array>
  </dict>
  <key>Managers/Request/RequestManager.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/RequestManager.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Request/RequestManagerType.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/RequestManagerType.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Managers/Request/Endpoint.swift</key>
  <dict>
   <key>Path</key>
   <string>Managers/Request/Endpoint.swift</string>
   <key>Group</key>
   <array>
    <string>Managers</string>
    <string>Request</string>
   </array>
  </dict>
  <key>Coordinators/Coordinator.swift</key>
  <dict>
   <key>Path</key>
   <string>Coordinators/Coordinator.swift</string>
   <key>Group</key>
   <string>Coordinators</string>
  </dict>
  <key>Coordinators/AppCoordinator.swift</key>
  <dict>
   <key>Path</key>
   <string>Coordinators/AppCoordinator.swift</string>
   <key>Group</key>
   <string>Coordinators</string>
  </dict>
  <key>Screens/SampleController/SampleViewController.swift</key>
  <dict>
   <key>Path</key>
  <string>Screens/SampleController/SampleViewController.swift</string>
   <key>Group</key>
   <array>
    <string>Screens</string>
    <string>SampleController</string>
   </array>
  </dict>
  <key>Views/SampleView/SampleView.swift</key>
  <dict>
   <key>Path</key>
   <string>Views/SampleView/SampleView.swift</string>
   <key>Group</key>
   <array>
    <string>Views</string>
    <string>SampleView</string>
   </array>
  </dict>
  <key>Resources/Assets.xcassets</key>
  <dict>
   <key>Path</key>
   <string>Resources/Assets.xcassets</string>
   <key>Group</key>
   <array>
    <string>Resources</string>
   </array>
  </dict>
  <key>Resources/Colors.xcassets</key>
  <dict>
   <key>Path</key>
   <string>Resources/Colors.xcassets</string>
   <key>Group</key>
   <array>
    <string>Resources</string>
   </array>
  </dict>
  <key>Resources/SwiftGen/swiftgen.yml</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/swiftgen.yml</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Resources/SwiftGen/Colors.swift</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/Colors.swift</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Resources/SwiftGen/Assets.swift</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/Assets.swift</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Resources/SwiftGen/Localizable.swift</key>
  <dict>
    <key>Path</key>
    <string>Resources/SwiftGen/Localizable.swift</string>
    <key>Group</key>
    <array>
      <string>Resources</string>
      <string>SwiftGen</string>
    </array>
  </dict>
  <key>Helpers/TypeAliases.swift</key>
  <dict>
    <key>Path</key>
    <string>Helpers/TypeAliases.swift</string>
    <key>Group</key>
    <string>Helpers</string>
  </dict>
  <key>Resources/.swiftlint.yml</key>
  <dict>
    <key>Path</key>
    <string>Resources/.swiftlint.yml</string>
    <key>Group</key>
    <string>Resources</string>
  </dict>
 </dict>
 <key>Nodes</key>
 <array>
  <string>Helpers/TypeAliases.swift</string>
  <string>Application/AppDelegate.swift</string>
  <string>Models/Response/SampleResponse.swift</string>
  <string>Models/Request/SampleRequest.swift</string>
  <string>Managers/Dependency/DependencyContainer.swift</string>
  <string>Managers/Request/RequestManager.swift</string>
  <string>Managers/Request/RequestManagerType.swift</string>
  <string>Managers/Request/Endpoint.swift</string>
  <string>Coordinators/Coordinator.swift</string>
  <string>Coordinators/AppCoordinator.swift</string>
  <string>Screens/SampleController/SampleViewController.swift</string>
  <string>Views/SampleView/SampleView.swift</string>
  <string>Resources/Colors.xcassets</string>
  <string>Resources/Assets.xcassets</string>
  <string>Resources/SwiftGen/swiftgen.yml</string>
  <string>Resources/Colors.xcassets</string>
  <string>Resources/Assets.xcassets</string>
  <string>Resources/Localizable.strings</string>
  <string>Resources/SwiftGen/Assets.swift</string>
  <string>Resources/SwiftGen/Colors.swift</string>
  <string>Resources/SwiftGen/Localizable.swift</string>
  <string>Resources/.swiftlint.yml</string>
 </array>
 <key>Targets</key>
	<array>
		<dict>
			<key>TargetIdentifier</key>
			<string>com.apple.dt.cocoaTouchApplicationTarget</string>
			<key>BuildPhases</key>
			<array>
				<dict>
					<key>Name</key>
					<string>🛠 Generate enums with SwiftGen</string>
					<key>SortOrder</key>
					<string>1</string>
					<key>Class</key>
					<string>ShellScript</string>
					<key>ShellPath</key>
					<string>/bin/sh</string>
					<key>ShellScript</key>
					<string>SWIFT_GEN="${PODS_ROOT}/SwiftGen/bin/swiftgen"
SWIFT_GEN_CONFIG="${PROJECT_DIR}/${PROJECT_NAME}/Resources/SwiftGen/swiftgen.yml"

if test -f "${SWIFT_GEN}"; then
    if test -f "${SWIFT_GEN_CONFIG}"; then
        "${SWIFT_GEN}" config run --verbose --config "${SWIFT_GEN_CONFIG}"
    else
        echo "warning: Swifgen configuration file missing make sure the path "$SWIFT_GEN_CONFIG" contains the file 😭😩🤦‍♂️"
    fi
else
    echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen 😭😩🤦‍♂️"
fi</string>
				</dict>
				<dict>
					<key>Name</key>
					<string>🧹 Validate codestyle with SwiftLint</string>
					<key>SortOrder</key>
					<string>1</string>
					<key>Class</key>
					<string>ShellScript</string>
					<key>ShellPath</key>
					<string>/bin/sh</string>
					<key>ShellScript</key>
					<string>SWIFT_LINT="${PODS_ROOT}/SwiftLint/swiftlint"
 SWIFT_LINT_CONFIG="${SRCROOT}/${PROJECT_NAME}/Resources/.swiftlint.yml"

if test -f "${SWIFT_LINT}"; then
    if test -f "${SWIFT_LINT_CONFIG}"; then
        "${SWIFT_LINT}" --config "${SWIFT_LINT_CONFIG}"
    else
        echo "warning: Swiflint configuration file missing make your the submodule is fetched 😭😩🤦‍♂️"
    fi
else
    echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint 😭😩🤦‍♂️"
fi</string>
				</dict>
			</array>
		</dict>
	</array>
  <key>Project</key>
	<dict>
			<key>SharedSettings</key>
			<dict>
					<key>SWIFT_VERSION</key>
					<string>5.0</string>
			</dict>
	</dict>
 </dict>
</plist>

This is what the finished project and its buildphases we created today can look like ⬇️

Voilà. After setting up the SPM dependency and installing the pods, we have generated assets and a swiftlint is running over the project.

Such scripts can be packaged very easily by adding additional build-phases. You can find a fully developed template as well as previous templates on our github. You will also find templates that are more advanced than these, on the main branch, so don't hesitate and give it a try.

Andrej JaššoiOS Developer