iOS

Xcode project templates Vol. 3: Ako automatizovať konfiguráciu swiftlintu a swiftgenu

Ako z názvu vyplýva v tomto článku ti ukážem návod, ako pridať runskripty a hotovú konfiguráciu swiftlintu a swiftgenu do projektu cez projektovú šablónu.

Andrej Jaššo5 Oct 2021

Skripty v projektoch väčšinou vyzerajú veľmi nekonzistentne v závislosti od počtu ľudí, ktorí nastavujú projekty. Ak však vždy použijete ten istý template nie je sa kde pomýliť. Takto vyzeral náš template v prechádzajúcom článku o 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>

Možno ste si všimli, že som pridal novú sekciu, ktorú môžete vidieť nižšie ⬇️

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

Toto je kvôli novému Xcode 13. Avšak dnes budeme pridávať do šablóny úplne novú sekciu Targets.

<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>

Kľúč Targets určuje zoznam projektových targets, ale my použijeme len jeden konkrétny a to ten predvolený hlavný target aplikácie, ktorú tvoríme. Pre toto je potrebné určiť ID targetu, ktoré je:

com.apple.dt.cocoaTouchApplicationTarget

Následne zadáme kľúč build phases, ktorý je opäť zoznam z tabu buildphases projektu.

Do premennej Name zadajte názov scriptu. S názvom sa môžete vyhrať a zadať aj rôzne emoji, ktoré vás hneď vizuálne ku skriptu nasmerujú.

  • SortOrder určí poradie scriptov.
  • Class musí byť pri štandardných sh scriptoch ShellScript
  • ShellPath štandardne takisto /bin/sh
  • ShellScript spúšťa knižnicu a zadávame cestu ku konfiguračnému súboru.

V rámci scriptov SWIFT_LINT_CONFIG určuje cestu ku konfiguračnému súboru, rovnako aj ANY_LINT_CONFIG a SWIFT_GEN_CONFIG.

Swiftgen lokalizácie by mali byť nastavené až po vybraní lokalizácii a základného jazyka appky. Ale pravdepodobný setup je aj tak uvedený v 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

Swiftlint može napísať podľa seba ale aj keď do konfiguračného súboru neuvediete nič. Swiftlint si zoberie prevolenú konfiguráciu.

Následne si do zložky pridáme swiftgen súbory a swiflint konfiguračný súbor do 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>

Do definitions pridáme:

<?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>

Výsledok vyzerá nasledujúco:

<?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>

Takto môže vyzerať hotový projekt a jeho buildphases, ktorý sme dnes vytvorili ⬇️

Voilà. Po nahodení SPM dependency a nainštalovaní podov máme vygenerované assety a nad projektom beží swiftlint.

Takéto scripty sa dajú nabaľovať veľmi jednoducho pridaním ďalších build-phases.

Plne vypracovaný template ako aj prechádzajúce templaty nájdete na našom githube.

Takisto tam nájdete templaty ktoré sú pokročilejšie oproti týmto. Na hlavnej branch, tak neváhajte a vyskúšajte si to.

Andrej Jaššo5 Oct 2021