
Náš iOS toolbox – sprístupnenie nášho code-base svetu

20. Sep 2021
iOSPri každom zakladaní nového projektu trvalo celý pracovný deň, kým som ho pripravil pre vývoj. Až kým som neobjavil šablóny. Xcode šablóny sú tu už od čias Xcode 4, avšak dozvedel som sa o nich až nedávno a úplne zmenili spôsob, ako sa pozerám an tvorbu projektu. Skús si ich somnou a nové projekty budú zrazu o to jednotnejšie a udržiavanejšie.
V predchádzajúcom článku o Xcode projet templates som vás previedol spustením tohto nástroja krok za krokom a poukázal na jeho výhody. Tentokrát vám predstavím ďalšie schopnosti Xcode projekt template-ov, kde pri vygenerovaní projektu budeme mať pripravený podfile s predvyplnenou konfiguráciou. Čo v praxi znamená, že po vygenerovaní vstúpime do projektu cez konzolu, zavoláme
pod install
a projekt bude mať pody nakonfigurované. Toto značne uberie na konfigurácii projektu a štýl podfilu bude jednotný pokiaľ sa jedná o komplexnejšie podfiles.
Ako prvé je potrebné vytvoriť nový template podobne, ako minule v zložke projektových templatov s koncovkou .xctemplate
Tu si najskôr vytvoríme súbor Podfile a dovnútra vložíme pody, ktoré chceme importovať do každého nového projektu.
platform :ios, '___VARIABLE_VERSION___'
target '___PACKAGENAME___' do
use_frameworks!
pod 'SwiftGen'
pod 'SwiftLint'
end
Všimnite si použitých premenných VARIABLE_VERSION, ktorá nastaví podom minimálnu verziu projektu a PACKAGENAME, ktorá nastaví názov projektu. Pri vytváraní projektu bude VARIABLE_VERSION vstupným parametrom a PACKAGENAME bude prevzaté od názvu projektu.
Následne je potrebné nakonfigurovať TemplateInfo.plist súbor, ktorý prestavuje konfiguráciu template-u
<?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> <!--States the template type-->
<string>Xcode.Xcode3.ProjectTemplateUnitKind</string>
<!--States if the template is a standalone template or a part
of template used in a diffrent template. In this case it will
be hidden from the template wizzard-->
<key>Concrete</key>
<true/>
<key>Identifier</key> <!--Template ID in the "template space"-->
<string>com.goodrequest.CocoaPods</string>
<key>Definitions</key> <!--Template variables-->
<dict>
<key>../Podfile</key>
<dict>
<key>Path</key>
<string>Podfile</string>
<key>Group</key>
<string>Resources</string>
</dict>
</dict>
<key>Options</key> <!--"USER INPUT" options-->
<array>
<dict>
<key>Identifier</key> <!--Option ID-->
<string>cocoapods</string>
<key>Name</key> <!--Field title-->
<string>CocoaPods</string>
<key>Description</key> <!--Field tooltip-->
<string>Integrate CocoaPods template</string>
<key>SortOrder</key> <!--Sorting priority-->
<integer>250</integer>
<key>Type</key> <!--Field type-->
<string>checkbox</string>
<key>Default</key> <!--Default value-->
<string>false</string>
<key>Units</key> <!--Field outcome-->
<dict>
<key>true</key> <!--True branch outcome-->
<array>
<dict>
<key>Nodes</key> <!--Files to include if True-->
<array>
<string>../Podfile</string>
</array>
</dict>
</array>
</dict>
</dict>
<dict>
<key>Identifier</key> <!--Option ID-->
<string>VERSION</string>
<key>Required</key> <!--Required to fill in the field-->
<true/>
<key>Name</key> <!--Field title-->
<string>iOS Min. Version</string>
<key>Description</key> <!--Field tooltip-->
<string>Minimum supported iOS version</string>
<key>Type</key> <!--Field type-->
<string>text</string>
<key>Default</key> <!--Default value-->
<string>13.0</string>
<key>NotPersisted</key> <!--Remember last filled in choice-->
<true/>
</dict>
</array>
</dict>
</plist>
Tu je podstatné si všimnúť si identifier premenne:
Tento template chceme teraz vložiť do nášho projektového templatu z minulého návodu.
Výsledok bude takýto:
<?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.apple.dt.unit.singleViewApplication</string>
<key>Ancestors</key>
<array>
<string>com.goodrequest.cocoaTouchApplicationBase</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>Extensions/Foundation/String+Extensions.swift</key>
<dict>
<key>Path</key>
<string>Extensions/Foundation/String+Extensions.swift</string>
<key>Group</key>
<array>
<string>Extensions</string>
<string>Foundation</string>
</array>
</dict>
<key>Extensions/UIKit/UIView+Extensions.swift</key>
<dict>
<key>Path</key>
<string>Extensions/UIKit/UIView+Extensions.swift</string>
<key>Group</key>
<array>
<string>Extensions</string>
<string>UIKit</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>Models/Error/AppError.swift</key>
<dict>
<key>Path</key>
<string>Models/Error/AppError.swift</string>
<key>Group</key>
<array>
<string>Models</string>
<string>Error</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>Screens/BaseViewController.swift</key>
<dict>
<key>Path</key>
<string>Screens/BaseViewController.swift</string>
<key>Group</key>
<array>
<string>Screens</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>
</dict>
<key>Nodes</key>
<array>
<string>Application/AppDelegate.swift</string>
<string>Extensions/UIKit/UIView+Extensions.swift</string>
<string>Extensions/Foundation/String+Extensions.swift</string>
<string>Helpers/TypeAliases.swift</string>
<string>Models/Error/AppError.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>Screens/BaseViewController.swift</string>
<string>Views/SampleView/SampleView.swift</string>
<string>Resources/SwiftGen/swiftgen.yml</string>
<string>Resources/Colors.xcassets</string>
<string>Resources/Assets.xcassets</string>
<string>Info.plist:UIMainStoryboardFile</string>
<string>Info.plist:UIApplicationSceneManifest:UISceneStoryboardFile</string>
</array>
</dict>
</plist>
Jedine v čom sa tieto súbory líšia je kľuč ancestors kde pridáme Identifier z templatu, ktorý sme práve vytvorili.
<key>Ancestors</key>
<array>
<string>com.goodrequest.cocoaTouchApplicationBase</string>
<string>com.goodrequest.CocoaPods</string> <!--ID of the Pod template-->
</array>
Teraz už stačí iba vytvoriť projekt cez template a vykonať nad repozitárom pod install a je to 🙂
Ďakujem za pozornosť.