New App - Xcode Templates

When starting a new app, after deciding which based design pattern you are going to use for the views, you can create some Xcode templates to help standardize how the files are written and speed up development.

For example, let’s say we decide to use MVVM for our SwiftUI views. We also decide we will have 3 files for each view:

  • MyView_Mocks.swift
  • MyView.swift
  • MyViewModel.swift

Create the Template

We can create a basic Xcode template that creates those 3 files with some basic code inside by following these steps:

  1. Navigate to ~/Library/Developer/Xcode/Templates. (Create the Templates folder if necessary).
  2. Create a new File Templates folder inside.
  3. Create a new folder called SwiftUIView-ViewModel.xctemplate inside File Templates.
  4. Create these 4 files inside the new folder (code below):
    • ___FILEBASENAME____Mocks.swift
    • ___FILEBASENAME___.swift
    • ___FILEBASENAME___Model.swift
    • TemplateInfo.plist

After this, reset Xcode and you will see this option when adding a new file: New File

The code for the files

You can customize these files to suit your needs:

View

//___FILEHEADER___
import SwiftUI
struct ___VARIABLE_ViewName___: View {
@StateObject private var viewModel: ViewModel
init(dependencies: ViewModel.Dependencies) {
_viewModel = StateObject(
wrappedValue: ViewModel(
dependencies: dependencies
)
)
}
var body: some View {
Text("___VARIABLE_ViewName___") // TODO: Replace the body
}
}
private extension ___VARIABLE_ViewName___ {
enum ViewConstants {
// TODO: Add constants here
}
}
struct ___VARIABLE_ViewName____Previews: PreviewProvider {
static var previews: some View {
NavigationView {
___VARIABLE_ViewName___(dependencies: .mock)
}
}
}

ViewModel

//___FILEHEADER___
import Foundation
extension ___VARIABLE_ViewName___ {
final class ViewModel: ObservableObject {
private let dependencies: Dependencies
init(dependencies: Dependencies = .default) {
self.dependencies = dependencies
}
}
}
extension ___VARIABLE_ViewName___.ViewModel {
struct Dependencies {
// TODO: Add dependencies here
var doSomething: () async throws -> Void
static var `default`: Self {
.init {
// TODO: Provide the default dependencies here
return
}
}
}
}
extension ___VARIABLE_ViewName___.ViewModel {
// TODO: Replace me
@MainActor
func doSomething() async {
do {
try await dependencies.doSomething()
} catch {
// Error handling
}
}
}
private extension ___VARIABLE_ViewName___.ViewModel {
}

Mocks

//___FILEHEADER___
import Foundation
extension ___VARIABLE_ViewName___.ViewModel.Dependencies {
static var mock: Self {
.init {
// TODO: Replace me
return
}
}
}

TemplateInfo.plist

<?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>SupportsSwiftPackage</key>
<true/>
<key>Kind</key>
<string>Xcode.IDEFoundation.TextSubstitutionFileTemplateKind</string>
<key>Description</key>
<string>A SwiftUI View with it&apos;s ViewModel and the Mocks</string>
<key>Summary</key>
<string>SwiftUI View + ViewModel + Mocks</string>
<key>SortOrder</key>
<string>1</string>
<key>AllowedTypes</key>
<array>
<string>public.swift-source</string>
</array>
<key>Platforms</key>
<array/>
<key>MainTemplateFile</key>
<string>___FILEBASENAME___.swift</string>
<key>Image</key>
<dict>
<key>FileTypeIcon</key>
<string>swift</string>
</dict>
<key>Options</key>
<array>
<dict>
<key>Description</key>
<string>The name of the view to create.</string>
<key>Identifier</key>
<string>ViewName</string>
<key>Name</key>
<string>New View Name:</string>
<key>NotPersisted</key>
<true/>
<key>Required</key>
<true/>
<key>Type</key>
<string>text</string>
</dict>
<dict>
<key>Default</key>
<string>___VARIABLE_ViewName:identifier___</string>
<key>Identifier</key>
<string>productName</string>
<key>Type</key>
<string>static</string>
</dict>
</array>
</dict>
</plist>

New App - Xcode Templates | manu.show
Tags: iOS tools
Share: X (Twitter) LinkedIn