Quando aprendemos a desenvolver em Swift e começamos a construir um projeto, nós temos que toda vez criar classes e mais classes. Um projeto simples pode conter cerca de 10 classes e projetos mais complexos podem ultrapassar 10000 classes tranquilamente e muitas dessas classes fazemos o processo de sempre que é File > New > File > Swift File.
Dessa forma criamos um arquivo Swift novo sem código e temos que adicionar toda a base do projeto e sabemos que dependendo da arquitetura do projeto acaba sendo um processo muito moroso e muitas vezes temos muito boilerplate code.
Boilerplate se refere a seções de código que devem ser incluídas em muitos lugares com pouca ou nenhuma alteração. Ele é muitas vezes usado quando se refere a linguagens que são consideradas detalhadas, onde o programador deve escrever muito código para fazer tarefas mínimas. (wikipedia)
Para evitar perder tempo escrevendo um código base ou até mesmo copiando de outras classes e apagando o que não faz sentido (e correr o risco de esquecer algo), podemos criar templates que facilita o nosso dia-a-dia e agiliza o nosso desenvolvimento.
Criando nosso template
Vamos começar do começo, onde fica esses arquivos de template? Simples, abra o seu finder e você pode buscar a pasta, para isso você pode usar o atalho command + shift + G
📁 ~
-> 📁 Library
-> 📁 Developer
-> 📁 Xcode
-> 📁 Templates
-> 📁 File Templates
Nesse diretório, ficará todos os templates que iremos criar. O template é separado por pastas que divide em seções ou em grupos. Vamos criar uma pasta chamada DevPoli, dessa forma ficando então:
📁 File Templates
-> 📁 DevPoli
Podemos dizer que essa pasta que criamos é a seção do nosso template que será exibida no XCode e aqui dentro você pode colocar vários templates para o projeto. Você deve criar uma pasta, que será nosso diretório do template, com a extensão .xctemplate.
Então vamos chamar de MVVM.xctemplate e dentro dessa iremos criar nosso arquivo de configuração do template chamado TemplateInfo.plist. Esse arquivo possui os campos de entrada e criação de variáveis que iremos usar no nosso projeto. Abra esse arquivo em algum editor de texto e adicione a seguinte estrutura:
<?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.IDEKit.TextSubstitutionFileTemplateKind</string>
<key>Platforms</key>
<array>
<string>com.apple.platform.iphoneos</string>
</array>
<key>SortOrder</key>
<string>1</string>
<key>AllowedTypes</key>
<array>
<string>public.swift-source</string>
</array>
</dict>
</plist>
Calma, vou explicar cada chave dessa, vamos lá:
Kind
Xcode.IDEKit.TextSubstitutionFileTemplateKind
Usado para template de substituição
Xcode.IDECoreDataModeler.ManagedObjectTemplateKind
Usado para template gerado pelo NSManagedObject
Platforms
Array de string com as plataformas compatíveis o template. Usado para especificar em qual projeto pode ser gerado.
com.apple.platform.macosx
com.apple.platform.iphoneos
com.apple.platform.watchos
com.apple.platform.appletvos
SortOrder
Posição do seu template na escolha do arquivo no XCode. Essa posição deve ser do tipo String.
AllowedTypes
Array de string usado para restringir qual tipo de arquivo pode salvar. Você pode encontrar os tipos no Uniform Type Identifiers. O tipo mais comum é:
public.swift-source
Dessa forma já temos um template funcional, basta criarmos agora o arquivo que será a base do nosso template. Dessa forma, vamos criar um arquivo swift dentro da pasta do nosso xctemplate. Segue o exemplo:
Repare que o nosso arquivo swift tem o nome ___FILEBASENAME___, essa tag é uma palavra chave ou também conhecida como MACRO que será substituída com o nome do arquivo salvo. Ou seja, se você criar um arquivo e salvar com o nome "MinhaViewController", será criado um arquivo "MinhaViewController.swift".
Agora você pode voltar no XCode e criar um novo arquivo e role para baixo e procure a seção DevPoli e lá estará o seu arquivo.
No seu projeto, deve aparecer sem o ícone bonitinho, mas logo logo vamos adicionar ele.
Se você selecionar o MVVM e apertar Next, na próxima tela você irá salvar o arquivo e pronto, temos o nosso primeiro template criado.
Tá, e agora?
Bom, imagino que se você veio para esse artigo é que você quer criar templates que irão facilitar sua vida e ter menos retrabalho na hora de desenvolver. Então vamos falar sobre isso agora.
Até agora vimos o básico do básico, que é termos um template reconhecido no XCode e conseguir abrir ele. Agora vamos adicionar opções para deixarmos mais complexo o projeto.
No nosso arquivo ___FILEBASENAME___.swift vamos adicionar a construção da nossa classe, segue o exemplo:
// ___FILEHEADER___
import Foundation
class ___FILEBASENAMEASIDENTIFIER___ {
}
Como dito anteriormente, existem macros que são definidas pelo próprio sistema, você pode usa-las para preencher partes do seu código com informações existentes. Para consultar as demais macros existentes, recomendo ler Text Macro Reference do XCode.
Mas basicamente a macro ___FILEBASENAMEASIDENTIFIER___ contém o nome do arquivo codificado como identificador para C.
Você pode salvar o arquivo e voltar no XCode e tentar carregar novamente o nosso template e pronto, temos nossa classe criada com o nome dinâmico baseado no nome do arquivo.
Vamos melhorar mais ainda, renomeie o arquivo do template ___FILEBASENAME___.swift para ___FILEBASENAME___ViewController.swift e na nossa classe, vamos mudar para o seguinte código.
// ___FILEHEADER___
import UIKit
final class ___FILEBASENAMEASIDENTIFIER___: UIViewController {
// MARK: - Layout
override func viewDidLoad(){
super.viewDidLoad()
}
}
Agora salve e volte para o XCode, se você criar o novo arquivo agora, iremos ter a classe criada com o mesmo nome do nosso arquivo e na hora de colocar o nome para salvar, você pode colocar somente o nome da sua funcionalidade sem precisar colocar ViewController no final, pois o nosso template já faz isso para gente. Ou seja, você pode salvar como "Login" que ele irá criar nosso arquivo chamado "LoginViewController" e a classe também terá esse nome.
Estrutura do MVVM
Também podemos trabalhar com mais de um arquivo no template, pensando na estrutura do MVVM que temos os arquivos ViewController e ViewModel, podemos seguir a mesma idéia de construção e ainda setar a base de referência.
📁 DevPoli
-> 📁 MVVM.xctemplate
-> 📄 TemplateInfo.plist
-> 📄 ___FILEBASENAME___ViewController.swift
-> 📄 ___FILEBASENAME___ViewModel.swift
Dessa forma como aprendemos teremos 2 arquivos e cada um com seu nome base definido, na construção do código, basta você montar da forma que deseja.
Mas para essa base funcionar, precisamos adicionar um parâmetro novo no nosso arquivo plist, para termos uma variável do nome do nosso projeto, pois como você deve ter percebido, o FILEBASENAME tem o nome do arquivo completo que é ViewController, mas não conseguimos ter acesso ao nome base para chamar a nossa ViewModel. Dessa forma vamos criar a nossa MACRO e usar ela.
Abra o arquivo TemplateInfo.plist e vamos adicionar uma nova chave que se chama Options:
<key>Options</key>
<array>
<dict>
<key>Identifier</key>
<string>productName</string>
<key>Required</key>
<true/>
<key>Name</key>
<string>Módulo:</string>
<key>Description</key>
<string>O nome da nossa ViewController e ViewModel</string>
<key>Type</key>
<string>text</string>
<key>Default</key>
<string>DevPoli</string>
</dict>
</array>
Key | Descrição | Tipo |
Name | Nome do campo | string |
Description | Descrição apresentada ao passar o mouse por cima do campo | string |
Type | Tipo da opção, podendo ser: checkbox, text, static, combo, popup | string |
Required | Desabilitar o botão de avançar caso o campo não esteja preenchido | bool |
Identifier | Identificador único do campo que será por variável | string |
Default | Valor padrão | string |
Values | Valores para tipo combo e popup | array of string |
RequiredOptions | Permite habilitar o campo somente se outro campo estiver preenchido com valor determinado | dictionary |
SortOrder | Define a ordem da posição do campo para ser exibido | number |
vou deixar o arquivo completo de exemplo:
<?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.IDEKit.TextSubstitutionFileTemplateKind</string>
<key>Platforms</key>
<array>
<string>com.apple.platform.iphoneos</string>
</array>
<key>SortOrder</key>
<string>1</string>
<key>AllowedTypes</key>
<array>
<string>public.swift-source</string>
</array>
<key>Options</key>
<array>
<dict>
<key>Identifier</key>
<string>productName</string>
<key>Required</key>
<true/>
<key>Name</key>
<string>Módulo:</string>
<key>Description</key>
<string>O nome da nossa ViewController e ViewModel</string>
<key>Type</key>
<string>text</string>
<key>Default</key>
<string>DevPoli</string>
</dict>
</array>
</dict>
</plist>
Assim temos a visualização do campo na hora de salvar o arquivo no XCode.
Repare que no arquivo eu usei o identificador productName, dessa forma estou informando ao XCode qual o nome base do nosso arquivo, dessa forma não preciso informar novamente o nome do arquivo. Essa tag é uma macro existente, então estou sobrescrevendo ela.
Agora podemos alterar nosso arquivo de template para usar as informações criadas. Vou deixar aqui um exemplo base, mas tudo depende da sua necessidade de trabalho e dependências.
📄 ___FILEBASENAME___ViewController.swift
// ___FILEHEADER___
import UIKit
final class ___FILEBASENAMEASIDENTIFIER___: UIViewController {
// MARK: - Dependencies
let viewModel = ___VARIABLE_productName:identifier___ViewModel()
// MARK: - Layout
override func viewDidLoad(){
super.viewDidLoad()
viewModel.start()
}
}
📄 ___FILEBASENAME___ViewModel.swift
// ___FILEHEADER___
import Foundation
final class ___FILEBASENAMEASIDENTIFIER___ {
func start(){
print("Aqui começa tudo!")
}
}
Para acessar nossa variável, devemos chamar da seguinte forma ___VARIABLE_productName:identifier___. O formato da macro definida é ___MACRO_nomeDaVariavel:modificador___, para consultar os modificadores você pode acessar a Referência de Macros. Mas para resumir, usamos:
MACRO => VARIABLE
nomeDaVariavel => O identificador criado na opção
modificador => identifier
E pronto, temos nosso template funcionando novamente e dinâmico. Vale lembrar que a definição da macro, você precisa colocar no início 3 underlines (_) e no final também.
Desafio
Quer treinar?
Agora fica um desafio para você, baseado nesse nosso aprendizado você deve criar um template para o ViewCode e modificar a ViewController para acessar a nossa View.
Estou deixando aqui embaixo para você baixar um template pronto do MVVM para você usar nos seus projetos. Baixe, configure, modifique, se divirta <3
Só acho que você deveria compartilhar nas redes e me ajudar :D
Deixe o gostei aqui no artigo que irei saber o que você achou e se você quiser, posso trazer uma parte 2 desse artigo onde podemos deixar o nosso template mais dinâmico ainda, com regras e validações específicas do projeto.
Comments