Xcode Project and File Templates
Learn how to create custom project and file templates in Xcode to start new projects and files more efficiently. By Keegan Rush.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Xcode Project and File Templates
30 mins
- Getting Started
- Understanding Default Templates
- Exploring Base Templates
- Exploring iOS Templates
- Creating Your First Project Template
- Contents of a Template
- Customizing the Project Template
- Working With Project Template Info
- Exploring Options
- Adding the View Model
- Using the Template
- Populating the Project
- Creating File Templates
- Copying a Default File Template
- Customizing the File Template Info
- Creating Template Files
- Using the Template
- Finishing the Project
- Where to Go From Here?
Creating Template Files
Inside Swift Enum.xctemplate, open ___FILEBASENAME___.swift. This is the file that your file template creates in your project.
___FILEBASENAME___
is a text macro that all file templates have. It’s the name that you choose for the file in the New File dialog, just without the file extension. For example, if you choose APIError.swift as the file name when using the template, then Xcode sets ___FILEBASENAME___
to APIError
.
Inside ___FILEBASENAME___.swift, replace the contents with this:
//___FILEHEADER___
import Foundation
enum ___FILEBASENAMEASIDENTIFIER___: ___VARIABLE_rawValue___ {
case one
case two
}
You’ve created a simple enum with two default cases. In this file, you use three template macros. Here’s what each of these do.
At the top of the file is ___FILEHEADER___
, which sets the usual copyright, file and author details.
Next, instead of a name for the enum, you have ___FILEBASENAMEASIDENTIFIER___
. This is the same as the ___FILEBASENAME___
variable for the file name, except that you can’t use ___FILEBASENAME___
inside the template file.
Finally, ___VARIABLE_rawValue___
is a reference to the rawValue
option you created earlier. The format looks like ___VARIABLE_
.
That’s all you need to set up your template. Quit and reopen Xcode. Next, you’ll use your template to create APIError.swift.
Using the Template
In Xcode, with Stellar Space open, go to File ▸ New ▸ File…. Then, choose your Swift Enum template.
For Raw Value, enter Error. Then, click Next.
Name the file APIError.swift and click Create.
Open APIError.swiftcases within APIError
and replace them with this:
case network(description: String)
case parsing(description: String)
Finally, build and run.
The app compiles! But, you still have some finishing touches to add to ContentView
and ViewModel
to display more than just a fancy message on the screen. :]
Finishing the Project
On the final stretch now to finish off the project to display those lovely NASA images.
In Xcode, open ViewModel.swift. First, add the following import at the top of the file:
import UIKit
Then, add the following under the declaration of title
:
@Published var image: UIImage?
@Published var errorMessage: String?
@Published var isLoading = true
@Published var date = Date()
var canMoveForward: Bool {
!calendar.isDateInToday(date)
}
var dateString: String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
return dateFormatter.string(from: date)
}
private let spaceImageFetcher = SpaceImageFetcher()
private let calendar = Calendar.current
private var disposables = Set<AnyCancellable>()
func changeDate(days: Int) {
if let newDate = calendar.date(byAdding: .day, value: days, to: date) {
date = newDate
loadImage()
}
}
func loadImage() {
isLoading = true
image = nil
errorMessage = nil
spaceImageFetcher.dailyPicture(date: date)
.receive(on: DispatchQueue.main)
.flatMap { dailyPic -> AnyPublisher<UIImage?, APIError> in
self.title = dailyPic.title
return self.spaceImageFetcher.loadImage(url: dailyPic.url)
}
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { [weak self] value in
switch value {
case .failure(let reason):
print("Failure: \(reason.localizedDescription)")
self?.errorMessage = "Something went wrong."
case .finished:
break
}
self?.isLoading = false
}, receiveValue: { image in
self.image = image
})
.store(in: &disposables)
}
I won’t explain the code here because it’s not relevant to the tutorial. All you need to know is that this code adds the logic for accessing the NASA API and displaying images.
Then, open ContentView.swift. Replace the declaration of body
with this:
var body: some View {
ZStack {
ColorPalette.primary.ignoresSafeArea()
VStack {
Text(viewModel.dateString)
.foregroundColor(ColorPalette.accent)
Spacer()
if !viewModel.isLoading {
if let image = viewModel.image {
Image(uiImage: image)
.resizable()
.scaledToFit()
Text(viewModel.title)
.foregroundColor(ColorPalette.accent)
} else if let error = viewModel.errorMessage {
Text(error)
.foregroundColor(ColorPalette.secondary)
}
Spacer()
ZStack {
HStack {
Button("Back", action: changeDateBack)
.padding(.leading, 20)
Spacer()
if viewModel.canMoveForward {
Button("Forward", action: changeDateForward)
.disabled(!viewModel.canMoveForward)
.padding(.trailing, 20)
}
}
}
} else {
ProgressView()
.progressViewStyle(ProgressViewWithBackgroundStyle())
.frame(width: 100, height: 100)
Spacer()
}
}
}
.onAppear(perform: fetchImage)
.buttonStyle(SpaceButtonStyle())
}
func changeDateBack() {
viewModel.changeDate(days: -1)
}
func changeDateForward() {
viewModel.changeDate(days: 1)
}
func fetchImage() {
viewModel.loadImage()
}
With this, ContentView
has the UI to display everything happening in ViewModel
. Build and run.
At last, you’ve completed Stellar Space, and you have two new Xcode templates to show for it: a project template and a file template!
Where to Go From Here?
In this tutorial, you created both a project template and a file template, using Xcode’s default templates as a source of inspiration.
You added your files to your templates, controlled them with the Template Options file and customized them with variables.
Templates are a great example of the power of an IDE like Xcode. If you’d like to learn more about how Xcode can make your life easier, iOS App Distribution & Best Practices dives under the hood of the Xcode project structure.
Your project template separates business logic from UI code by including a view model. If you’d like to learn more about project architecture, have a look at Advanced iOS App Architecture. You might get some ideas for new templates, too!
Please join the discussion below if you have questions or comments or want to share some of your creative templates.