Como criar um tutorial de Swift Playground App

Bruno Pastre
Apple Developer Academy PUCPR
6 min readApr 19, 2022

Entenda como funciona o recurso de tutoriais no Swift Playground App e utilize um template para criá-los rapidamente

Introdução

Os tutoriais presentes no Playground App são o recurso que mais se assemelha às páginas do Playground Book, nos dando espaço para falar sobre o nosso app dentro do app em si.

O tutorial é feito utilizando uma linguagem que deriva dos Tutoriais escritos em DocC. Basicamente, escrevemos diretivas (comandos que começam com @) que indicam a hierarquia de cada componente do nosso tutorial. É como se as diretivas fossem views do SwiftUI, e cada uma altera o tutorial de uma forma diferente.

A dificuldade em criar um tutorial é que, além de não ter documentação, ele precisa ser convertido em pelo menos um idioma para funcionar, o que implica em criarmos um arquivo binário contendo as chaves de localização de cada String do tutorial. Chato, né? Para isso, criamos um template com um script que faz toda a parte chata pra você! Ele funciona com as diretivas @GuideBook, @Guide, @Step, @ContentAndMedia, @Task e @Page, fazendo a geração automática para o idioma inglês.

Parte 1 — usando o Template

Baixando o template

Começe baixando o arquivo de template. Ele conta com um script para gerar o arquivo de idiomas e uma action que roda o script antes de buildar o projeto.

Download do Template

Buildando o template

Como o script só roda quando o projeto é construído (aka: build) É IMPORTANTE SEMPRE RODAR O PROJETO QUANDO MODIFICAR O WALKTHROUGH, OU NENHUMA ALTERAÇÃO SERÁ REFLETIDA EM SEU PLAYGROUND!!!. Para rodar o projeto, aperte Cmd + B

Pontos importantes

  • 🚨 É IMPORTANTE SEMPRE RODAR O PROJETO QUANDO MODIFICAR O WALKTHROUGH, OU NENHUMA ALTERAÇÃO SERÁ REFLETIDA EM SEU PLAYGROUND!!!
  • Infelizmente, não conseguimos fazer nenhum indicativo de sucesso ou falha da execução do script. Ou seja, se por qualquer motivo a execução do script falhar, ou o arquivo que ele gerar não estiver exatamente no formato certo: vai dar ruim. Isso não afeta em nada o código do seu app, mas o tutorial pode mostrar alguns textos estranhos, ou até mesmo nem aparecer
  • Ao fim de sua execução, o script fala DONE. Essa é a única forma que achamos de indicar que o script rodou. Caso fique chato, vá em Product > Scheme > Edit Scheme > Build -> Pre-actions e retire a linha say "Done”. O script continuará a rodar, mas agora sem declarar que terminou
  • Mantenha uma separação consistente entre as linhas de código. É recomendado sempre manter o espaçamento de uma linha entre as linhas de código, para garantir que o script funcione direito
  • Se durante o desenvolvimento surgir um alerta pedindo para atualizar o Playground e seu Playground já está atualizado, saiba que há um problema no seu arquivo Walkthrough.tutorial

Caso você esteja vendo essa tela, deu boa! Cada alteração, basta buildar novamente!

Adicionando texto

Pode trocar o texto dentro de @ContentAndMedia. Para criar outro parágrafo, basta pular uma linha!

Adicionando uma imagem

Basta arrastar o seu arquivo .png para dentro da pasta de Resources e adicionar a linha ![](nomeDoArquivo.png) dentro da diretiva @ContentAndMedia

Parte 2 — Criando um guia

Nosso objetivo nesse tutorial é criar um tutorial que ensina a estrutura do seguinte código

import SwiftUIstruct ContentView: View {
var body: some View {
Text("Hello World!")
}
}

Esse código está dentro do arquivo ContentView.swift.

Começamos então, criando o nosso tutorial no arquivo Walkthrough.tutorial e colocando as seguintes linhas:

@GuideBook(title: "Hello World", icon: title.png, background: titleBackground.png, firstFile: ContentView.swift) {}

A diretiva @GuideBook declara a criação de um livro de Playground App. Vamos, então, criar um guia, e adicionar a esse guia um passo

@GuideBook(title: "Hello World", icon: title.png, background: titleBackground.png, firstFile: ContentView.swift) {
@Guide {
@Step(title: "Understanding a Hello World in SwiftUI") {
}
}
}

Todos os passos precisam ter um conteúdo, e para isso usamos a diretiva @ContentAndMedia

@GuideBook(title: "Hello World", icon: title.png, background: titleBackground.png, firstFile: ContentView.swift) {
@Guide {
@Step(title: "Understanding a Hello World in SwiftUI") {
@ContentAndMedia {
This is a walkthrough on the structure of a SwiftUI Hello World view!
}
}
}
}

Colocamos um texto dentro de ContentAndMedia que descreve o que estaremos fazendo. Se buildarmos agora, devemos ter o seguinte resultado

Legal! Vamos começar a criar o tutorial?

Agora, criaremos, dentro do nosso @Step, uma diretiva de @Task

@GuideBook(title: "Hello World", icon: title.png, background: titleBackground.png, firstFile: ContentView.swift) {
@Guide {

@Step(title: "Understanding a Hello World in SwiftUI") {

@ContentAndMedia {

This is a walkthrough on the structure of a SwiftUI Hello World view!

}

@Task(type: walkthrough, title: "Analyze code", id: "contentView", file: ContentView.swift) {

}
}
}
}

Além de criar a task no tutorial, precisamos também referenciá-la dentro do código. Dentro do arquivo ContentView.swift, colocaremos um comentário especial que conecta o id da task ao arquivo de código do nosso App. Esse comentário é //#-learning-task(contentView). Reparem que o comentário parece uma chamada de função, e o “argumento", dessa função é o ID da task. O arquivo ContentView.swift fica assim

import SwiftUI
//#-learning-task(contentView)
struct ContentView: View {
var body: some View {
Text("Hello world!")
}
}

Mas nossa task não funciona sem páginas, então vamos criar uma que indica qual a declaração da view

@GuideBook(title: "Hello World", icon: title.png, background: titleBackground.png, firstFile: ContentView.swift) {
@Guide {

@Step(title: "Understanding a Hello World in SwiftUI") {

@ContentAndMedia {

This is a walkthrough on the structure of a SwiftUI Hello World view!

}

@Task(type: walkthrough, title: "Analyze code", id: "contentView", file: ContentView.swift) {
@Page(id: "ContentView.declaration", title: "Custom SwiftUI View") {
This is a custom SwiftUI view. It is used to encapsulate a view's content
}
}
}
}
}

Reparem também que colocamos um texto dentro da página. É esse texto que será mostrado dentro do balão. Bora buildar e ver como está?

Legal! Nossa tarefa já aparece ali! Ao clicarmos nela, vemos que aparece um balão com o texto que escrevemos dentro de @Page. Mas podemos melhorar ainda mais esse tutorial, né? Vamos começar adicionando um texto explicativo sobre o passo a passo

@GuideBook(title: "Hello World", icon: title.png, background: titleBackground.png, firstFile: ContentView.swift) {
@Guide {

@Step(title: "Understanding a Hello World in SwiftUI") {

@ContentAndMedia {

This is a walkthrough on the structure of a SwiftUI Hello World view!

}

@Task(type: walkthrough, title: "Analyze code", id: "contentView", file: ContentView.swift) {
In this task, we will analyze the structure of a SwiftUI view that displays the text "Hello, World!"
@Page(id: "ContentView.declaration", title: "Custom SwiftUI View") {
This is a custom SwiftUI view. It is used to encapsulate a view's content
}
}
}
}
}

Agora aparece um texto! Mas ainda podemos ser mais assertivos e indicar ao usuário qual a estrutura no código que representa a view customizada no SwiftUI. Para isso, usaremos o comentário /*#-code-walkthrough(ContentView.declaration)*/.

import SwiftUI
//#-learning-task(contentView)
/*#-code-walkthrough(ContentView.declaration)*/
struct ContentView: View {
var body: some View {
Text("Hello world!")
}
}
/*#-code-walkthrough(ContentView.declaration)*/

Reparem que o comentário também tem uma estrutura de função, e o argumento é o id da página. Além disso, esses comentários sempre vem aos pares, o que quer dizer que o que será selecionado é o que está entre a ocorrência de dois comentários iguais. Assim, sempre que a página é mostrada, o Playground App deve selecionar as linhas corretas

É isso. Basta adicionar mais páginas que o botão de done vira um botão de próximo, e quando o usuário navega até a última página, o botão de próximo automaticamente vira um botão de done.

Podemos também adicionar mais comentários especiais no código, fazendo com que diferentes páginas marquem diferentes partes do código

--

--