HOW TO BEAT A ROUTINE, OR A COMPLETE 
XCODE APPLICATION IN A COUPLE OF CLICKS

HOW TO BEAT A ROUTINE, OR A COMPLETE XCODE APPLICATION IN A COUPLE OF CLICKS

Every experienced developer has a set of tools that he is used to and that he is comfortable working with. This can be the simplest setting of the environment, utilities for intermediate operations (for example, the API Postman testing assistant), libraries and snippets that have been tested by time and personally by the developer.

Also, many developers may have their own approach to the implementation of the chosen architecture. Therefore, it is very useful to have an application blank in your arsenal – a general skeleton (framework), to which you only remain to add new modules, screens and features. In this article, I will show you how to create your own application template in Xcode.

Where is the heart of the template

How often do you create applications and write the same code over and over again, creating the base of a future product? You declare base classes, make helpers, embed the architecture, create wrappers... At such moments, you want to have a tool that will allow you to instantly get a working application with a well-developed architecture and a written base for further development.

Such a tool exists, and we all use it all the time when we create a 'Single View App' in Xcode.

My search for instructions from Apple on how to create your own templates was fruitless. However, Xcode allows you to add the generation of your own files with already prepared code, and it’s a tea party.

For an easy start, let's take the well-known Single View App. Go to Finder, press the key combination Cmd + Shift + G (jump to folder) and specify the path:

/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project Templates/iOS/Application

We find “Single View App.xctemplate” there and copy it, for example, to the desktop.

As you can see, the template consists of only 4 files:

  • Main.storyboard. Storyboard containing the main view controller
  • TemplateIcon.png. Icon with 48x48 definition
  • [email protected]. Icon with 96x96 definition
  • TemplateInfo.plist. Configuration file for the template

Only the last file, TemplateInfo.plist, plays a significant role here, because it contains all the settings. Main.storyboard is just one of the possible files that will be added to every application created from this template. In the absence of the second and third files from this list, your template will have a default icon. Therefore, the heart of the template is TemplateInfo.plist.

Main properties of the configuration file

Nominally, TemplateInfo properties can be divided into several categories:

1. Template markup

Assigning a template a unique ID and additional fields for display in the Xcode environment.

Required fields:

—?Identifier

Unique identificator. Two templates with the same ID cannot exist at the same time. Also used for inheritance in other templates.

—?Kind

Template type. Xcode.Xcode3.ProjectTemplateUnitKind are always used for projects

—?Concrete

A field that indicates whether the template will appear in the list when a new application is created. It makes sense to put NO when it is called from another template and is not independent itself. Otherwise, always set YES.

Optional fields:

—?Platforms

Specifies what platforms the template is used for. Only useful for preventing inheritance in templates for other platforms (for example, when trying to import an iOS template into a WatchOS one).

—?Name

The display name for the template. The default directory name is *.xctemplate.

—?SortOrder

Serial number. If there is no such field, it is considered as the last one.

—?Description

Description of the template. It is not displayed in the latest Xcode versions.

2. Inheritance

Templates in Xcode have a very useful property: they can include properties and files from other templates. It is very useful if there is a need to extend a template with additional features from another one without copying the files again and without editing the configuration file. A direct analogy is inheritance in OOP.

3. Ancestors

List of Identifier-templates which properties and files will be included in the project.

4. Content generation

You can fill a new application with both ready-made files, and by setting their generation in the settings.

P.S. Since projects can be created using both Objective-C and Swift, it must be taken into account that file generation must be written for different languages separately.

To do this, the Options field is created, which is an array. As the first element, we create a Dictionary and create two keys. The first is an Identifier of type String with the value "languageChoice". The second is Units, which is a Dictionary. In Units, we create two more Dictionaries with the names "Objective-C" and "Swift", respectively. All the Definitions and Nodes created in the future are placed inside these directories. If there is no language binding (for example, we want to add xib, storyboard or register content for a file), then Definitions and Nodes can be declared at the same level as the rest of the parameters.

No alt text provided for this image

Accordingly, if the file has no embedding and lies directly in .xctemplate/, then the Group array is not created.

6. Nodes

After we have specified the file paths, we need to create links. With their help we will point either to the created file or to the content. Nodes is a regular array, and its elements are keys from Definitions. For the above mentioned example, Nodes would look like this:

No alt text provided for this image

Code generation inside TemplateInfo.plist

You can add code to a file created in TemplateInfo.plist by writing it in Definitions and referencing it in Nodes. This is done by using the ":" operator after specifying the file, and the code is written afterwards. For example, in the default "Page-Based App" template, you can see that the Definitions describe a lot of code generation:

No alt text provided for this image

The order of the code in the file depends on the order of the links in the Nodes array. It will be created in case the specified file does not exist.

The following constants work in pre-created files and inside TemplateInfo.plist:

___COPYRIGHT___ Copyright line

___DATE___ Project (file) creation date

___DIRECTORY___ Full path to the file

___FILEBASENAME___ File name without extension

___FILEEXTENSION___ File extention

___FILENAME___ Full file name

___FULLUSERNAME___ Username authorized in the system

___ORGANIZATIONNAME___ The name of the organization specified when the project was created

___PACKAGENAME___ / ___PROJECTNAME___ The product name specified when the project was created

___TIME___ The time the project (file) was created

___USERNAME___ Authorized user account name

Editing the application settings window

When creating a template, you can also edit the application settings window which will later appear when this template is called.

For example, for the “Single View App”, Apple offers us several text fields for entering the developer name and the name of the organization, several checkboxes for including unit tests or CoreData in the project, as well as a drop-down list for choosing a programming language. All this is regulated by the Options field - an array from the Dictionary. For each option, the following list of options is available:

—?Identifier

An identifier which allows to change or use the value stored in the option field.

—?Default

The value that will be used by default for this field.

—?SortOrder

The sequence number by which this option will be displayed in the window.

—?Nae

The title for the option.

—?Type

The type of the originating field. There are the following fields types:

  • Static.?Static, non-editable text. In terms of meaning, it is nothing more than a Label.
  • Checkbox.?Regular checkbox. Since it is inherently a Bool-field, you also need to define Units for it, which will contain the appropriate set of actions for true and false values. An example of usage can be found in the “Core Data Cocoa Touch App.xctemplate” base template, which will be mentioned in the template creation section.
  • Text.?Text input field.
  • Popup.?Provides a selection from a drop-down list which must be defined in the Values array.

Creating an application template

Before we start, we need to prepare the files with the written code that we want to see in the application created according to our template.

For starters, let's create a directory where the templates we created will be stored. To do this, in the console, execute the command:

$ mkdir -p ~/Library/Developer/Xcode/Templates/Project\ Templates/Private

This is the path Xcode will look for application templates. You can name the Private folder as you wish, as long as it is located along this path. There may be several such directories, but the templates embedded in them must have a different Identifier. Otherwise, the existence of the template in all but one directory will be ignored.

Rename the “Single View App.xctemplate” copied earlier to “MVVM Application.xctemplate” and copy it to the Private folder. If you now launch Xcode and go to the menu for creating a new application, you can already see at the very bottom a new Private section, where there will be one single “MVVM Application” template. Since we have not changed anything yet, when using it, we will get the same Single View App (which, by the way, disappeared from the list of basic ones, because it has the same Identifier).

The next step is to transfer the Presentation folder and two icon files - TemplateIcon.png and [email protected]. Now we need to change the Identifier so that Xcode sees our template as a brand new one. For example, let's set the Identifier to "MVVMTemplate". Now, when creating a new application in Xcode, we will see that the “Single View App” has returned to its proper place, and in the Private section, “MVVM Application” flaunts with our icon.

Next, let's see what templates "Single View App" inherits from. Opening TemplateInfo.plist and go to Ancestors, we see:

com.apple.dt.unit.storyboardApplication

com.apple.dt.unit.coreDataCocoaTouchApplication

Templates with these identifiers are located in the same place as the “Single View App”. Let's sort it out in order.

The first template "Storyboard App.xctemplate" contains only the configuration file, in which you can see the Definitions and Nodes fields. They state that Main.storyboard will be used as the main storyboard, and the path to it is indicated. We don't need it, because we already have a MainScreen.storyboard file that we want to use as the main one. Therefore, we are removing the "Storyboard App.xctemplate" template from Ancestors.

Next comes the “Core Data Cocoa Touch App.xctemplate” template. A checkbox field is added to its options for the possibility of using CoreData, and all the necessary code generation and import of the ___PACKAGENAMEASIDENTIFIER___.xcdatamodeld file are registered in the Units field. Let's say that we don't need CoreData either, and also delete this parent.

But here's the problem: if we now try to create an application according to our template, then it will not be visible in the list. The fact is that the parents we deleted, in turn, also had the Ancestors list, which contained the necessary base template “Cocoa Touch App Base” with the com.apple.dt.unit.cocoaTouchApplicationBase identifier. By adding it to the list of Ancestors of our template, we will return it to the list of available ones again. By carefully studying this basic template, you will understand why it is so necessary, and we move on.

Now let's register all the paths and links for the copied files. Since the code is written for Swift, I will do this only for it.

Go to Options -> languageChoice (Item 0) -> Units -> Swift and create a Dictionary here called Definitions. Now let's write out all the paths to the files that we have:

Presentation/Common/View Controller/Base/ViewController.swift

Presentation/Common/View Model/Base/ViewModel.swift

Presentation/Common/View Model/ViewModelHolder.swift

Presentation/Main Screen/MainScreen.storyboard

Presentation/Main Screen/View Controller/MainViewController.swift

Presentation/Main Screen/View Model/MainViewModel.swift

We get the following list:

No alt text provided for this image

Now we fill in the Nodes links, it will look like this:

No alt text provided for this image

It remains to add the final touch – to put MainScreen.storyboard as the main one. Create Definitions and Nodes for the entire file and add the following fields to them:

Definitions:

Key

Info.plist:UIMainStoryboardFile

Value

<key>UIMainStoryboardFile</key
<string>MainScreen</string>>        

Nodes:

Info.plist:UIMainStoryboardFile

We get the following:

No alt text provided for this image

In the example I attached, there is a ready-made version of the TemplateInfo.plist file.

This article does not cover all the features for creating templates and files. It is simply not possible to include a description of each parameter here. Therefore, in the repository where the example is located, I have enclosed the documentation (unofficial) which describes all the possibilities and spells out all the existing parameters (at the time of Xcode 4 existence). Most of the functions can be understood by digging into the basic templates from Apple, at the same time seeing their implementation. I just described the necessary minimum for the simple creation of plain templates.

If you want to leave a feedback, you can always email us to?[email protected]. Thank you!

要查看或添加评论,请登录

MSOFT的更多文章

社区洞察

其他会员也浏览了