Para quem quer começar a programar com a linguagem Swift, esse artigo fornecerá uma introdução rápida aos conceitos e recursos mais importantes da linguagem.
Instalando Swift
O primeiro passo para usar Swift é baixar e instalar o compilador e outros componentes necessários. Vá para a página de Download e siga as instruções para a sua plataforma.
Para poder seguir com o exemplos abaixo, certifique-se de adicionar o Swift ao seu $PATH.
No macOS
A localização padrão do pacote que você baixou no macOS é o /Library/Developer/Toolchains
. Você pode fazer com que as ferramentas fiquem disponíveis para uso no terminal com o seguinte comando:
$ export PATH=/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin:"${PATH}"
No Linux
Em primeiro lugar, instale o clang:
$ sudo apt-get install clang
Se você instalou o pacote do Swift em algum outro diretório que não fosse a raiz do sistema, irá precisar executar o seguinte comando, usando caminho de sua instalação do Swift:
$ export PATH=/path/to/Swift/usr/bin:"${PATH}"
Você pode verificar que esta usando a versão esperado do Swift digitando o comando swift e passando como parâmetro a flag –version:
$ swift --version
Apple Swift version 2.2-dev (LLVM ..., Clang ..., Swift ...)
O sufixo -dev no número da versão é usado para indicar que se tratado de uma versão de desenvolvimento, não uma versão de lançamento.
Usando a REPL
Se você executar o comando swift sem nenhum argumento, você executará o REPL, um shell interativo que irá ler, processar e imprimir o resultado que qualquer código Swift que você digitar:
$ swift
Welcome to Apple Swift version 2.2. Type :help for assistance.
1>
Interagir com o REPL é uma ótima forma de experimentar com o Swift. Por exemplo, se você digitar a expressão 1 + 2, o resultado da expressão, 3, é impresso na linha seguinte:
1> 1 + 2
$R0: Int = 3
Você pode associar valores para constantes e variáveis, e usa-las em linhas subsequentes. Por exemplo, o valor String “Hello, world!” pode ser associado à contante greeting, e então passada como argumento para a função print(_:).
2> let greeting = "Hello!"
greeting: String = "Hello!"
3> print(greeting)
Hello!
Se você digitar uma expressão inválida, o REPL irá exibir um erro mostrando onde o problema ocorreu:
let answer = "forty"-"two"
error: binary operator '-' cannot be applied to two 'String' operands
let answer = "forty"-"two"
~~~~~~~^~~~~~
Você pode usar seta-pra-cima ou seta-pra-baixo para mover-se pelas linhas digitadas no REPL. Isso permite que você faça pequenas alterações em uma expressão anterior sem ter que redigitar a linha inteira, e isso é especialmente conveniente para corrigir error como o do exemplo anterior:
let answer = "forty-two"
answer: String = "forty-two"
Um outro recursos útil do REPL é que ele pode sugerir automaticamente funções e método que pode ser usado em um contexto em particular. Por exemplo, se você digitar re depois que o operador ponto em um valor String e apertar a tecla TAB, o REPL irá lhe fornecer uma lista de sugestões disponíveis como remove(at:) e replaceSubrange(bounds:with:):
5> "Hi!".re⇥
Available completions:
remove(at: Index) -> Character
removeAll() -> Void
removeAll(keepingCapacity: Bool) -> Void
removeSubrange(bounds: ClosedRange<Index>) -> Void
removeSubrange(bounds: Range<Index>) -> Void
replaceSubrange(bounds: ClosedRange<Index>, with: C) -> Void
replaceSubrange(bounds: ClosedRange<Index>, with: String) -> Void
replaceSubrange(bounds: Range<Index>, with: C) -> Void
replaceSubrange(bounds: Range<Index>, with: String) -> Void
reserveCapacity(n: Int) -> Void
Se você iniciar um bloco de código, como quando iterando um array em um loop for-in, o REPL irá automaticamente identar a linha seguinte, e irá alterar o prompt de > para um ponto para indicar que o código digitado nessa linha irá ser executado apenas quando o bloco inteiro for processado.
6> let numbers = [1,2,3]
numbers: [Int] = 3 values {
[0] = 1
[1] = 2
[2] = 3
}
7> for n in numbers.reversed() {
8. print(n)
9. }
3
2
1
Todas as funcionalidades do Swift estão disponíveis para você no REPL, da criação de sentenças de controle de fluxo à declaração de estruturas e classes.
Você também pode importar módulos do sistema, como o Darwin no macOS ou a Glibc no linux:
No macOS
1> import Darwin
2> arc4random_uniform(10)
$R0: UInt32 = 4
No Linux
1> import Glibc
2> random() % 10
$R0: Int32 = 4
Usando o Gerenciador de pacotes
O gerenciados de pacotes do Swift fornece um sistema convencional para criar bibliotecas e executáveis, e compartilhar código entre projetos diferentes.
Esses exemplo assumem que você tenha adicionado o swift em seu PATH; veja a seção de Instalação para mais informações. Uma vez que esteja disponível, você pode invocar as ferramentas do gerenciador de pacotes: swift package, swift build e swift test.
$ swift package --help
OVERVIEW: Perform operations on Swift packages
...
Criando um pacote
Para criar um novo pacote Swift. crie um novo diretório chamado Hello
:
$ mkdir Hello
$ cd Hello
Todo pacote precisa ter um arquivo de manifesto chamado Package.swift
em seu diretório raiz. Você pode criar um pacote minimo usando:
$ swift package init
Por padrão, o comando init irá criar um pacote com a seguinte estrutura:
├── Package.swift
├── Sources
│ └── Hello.swift
└── Tests
├── HelloTests
│ └── HelloTests.swift
└── LinuxMain.swift
Você pode usar swift build
para compilar o pacote. Isso irá baixar, determinar e compilar as dependências mencionadas no arquivo de manifesto Package.swift
.
$ swift build
Compile Swift Module 'Hello' (1 sources)
Para executar testes em um pacote, use: swift test
$ swift test
Compile Swift Module 'HelloTests' (1 sources)
Linking ./.build/debug/HelloPackageTests.xctest/Contents/MacOS/HelloPackageTests
Test Suite 'All tests' started at 2016-08-29 08:00:31.453
Test Suite 'HelloPackageTests.xctest' started at 2016-08-29 08:00:31.454
Test Suite 'HelloTests' started at 2016-08-29 08:00:31.454
Test Case '-[HelloTests.HelloTests testExample]' started.
Test Case '-[HelloTests.HelloTests testExample]' passed (0.001 seconds).
Test Suite 'HelloTests' passed at 2016-08-29 08:00:31.455.
Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'HelloPackageTests.xctest' passed at 2016-08-29 08:00:31.455.
Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds
Test Suite 'All tests' passed at 2016-08-29 08:00:31.455.
Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.002) seconds
Criando um executável
Um pacote é considerado como um executável se possuir um arquivo chamado main.swift
. O gerenciados de pacote irá compilar esse arquivo em um binário executável.
No nosso exemplo, o pacote produzirá um executável chamado Hello
que produzirá a saída “Hello, world!”.
Em primeiro lugar crie um diretório chamado Hello
:
$ mkdir Hello
$ cd Hello
Agora execute o comando init com o tipo executable:
$ swift package init --type executable
Compile o pacote executando o comando swift build
:
$ swift build
Depois que o comando for finalizado, o resultado da compilação estará disponível no diretório .build
. Execute o programa Hello
com o seguinte comando:
$ .build/debug/Hello
Hello, world!
No próximo passo vamos definir uma nova função sayHello(name:)
em um novo arquivo de código, e fazer com que o executável chame essa função ao invés de chamar diretamente print(_:)
.
Trabalhando com múltiplos arquivos de código
Crie um novo arquivo no diretório Sources/
com o nome Greeter.swift
, e digite nele o seguinte código:
func sayHello(name: String) {
print("Hello, \(name)!")
}
A função sayHello(name:)
recebe um único argumento do tipo String e imprime a nossa mensagem “Hello” de antes, substituindo a palavra “world” pelo nosso argumento.
Agora abra o arquivo main.swift
novamente, e substitua o código existente pelo código seguinte:
if CommandLine.arguments.count != 2 {
print("Usage: hello NAME")
} else {
let name = CommandLine.arguments[1]
sayHello(name: name)
}
Ao invés de usar um nome definido no código como antes, main.swift
agora lê os argumentos passados pela linha de comando. E ao invés de invocar diretamente print(_:)
, main.swift
agora chama o método sayHello(name:)
. Como o método é parte do módulo Hello
, nenhuma sentença import
é necesária.
Execute swift build
and e teste a nova versão de Hello
:
$ swift build
$ .build/debug/Hello `whoami`
Para aprender mais sobre o Gerenciador de pacotes do Swift, incluindo como compilar módulos, importar dependências e mapear bibliotecas do sistema, veja o artigo Swift Package Manager no site oficial.
Usando o depurador LLDB
Você pode usar o depurador LLDB para executar programas Swift passo a passo, configurar breakpoints e inspecionar e modificar o estado do programa.
Como exemplo, considere o seguinte código, que define uma função factorial(n:)
, e imprime o resultado da chamada a essa função:
func factorial(n: Int) -> Int {
if n <= 1 { return n }
return n * factorial(n: n - 1)
}
let number = 4
print("\(number)! is equal to \(factorial(n: number))")
Crie um arquivo com o nome Factorial.swift
com o código acima, e execute o comando swiftc
, passando como argumento o nome do arquivo, junto com a opção -g
para gerar as informações de depuração. Isso irá criar um executável chamado Factorial
no diretório atual.
$ swiftc -g Factorial.swift
$ ls
Factorial.dSYM
Factorial.swift
Factorial*
Ao invés de executar o programa Factorial
diretamente, execute-o através do depurador LLDB informado ele como argumento para o comando lldb
.
$ lldb Factorial
(lldb) target create "Factorial"
Current executable set to 'Factorial' (x86_64).
Isso irá iniciar um console interativo que permite que você execute comando do LLDB.
Para mais informações sobre o LLDB, veja o LLDB Tutorial.
Configure um breakpoint na linha2 da função factorial(n:)
com o comando breakpoint set
(b
), para que o processo seja interrompido a cada vez que a função seja executada.
(lldb) b 2
Breakpoint 1: where = Factorial`Factorial.factorial (Swift.Int) -> Swift.Int + 12 at Factorial.swift:2, address = 0x0000000100000e7c
Execute o processo com o comando run
(r
).O processo irá ser interrompido quando a função factorial(n:)
é chamada.
(lldb) r
Process 40246 resuming
Process 40246 stopped
* thread #1: tid = 0x14dfdf, 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2
1 func factorial(n: Int) -> Int {
-> 2 if n <= 1 { return n }
3 return n * factorial(n: n - 1)
4 }
5
6 let number = 4
7 print("\(number)! is equal to \(factorial(n: number))")
Use o comando print
(p
) para inspecionar o valor do parâmetro n
.
(lldb) p n
(Int) $R0 = 4
O comando print
pode executar expressões Swift também.
(lldb) p n * n
(Int) $R1 = 16
Use o comando backtrace
(bt
) para exibir os frames que levaram à invocação da função factorial(n:)
.
(lldb) bt
* thread #1: tid = 0x14e393, 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x0000000100000e7c Factorial`Factorial.factorial (n=4) -> Swift.Int + 12 at Factorial.swift:2
frame #1: 0x0000000100000daf Factorial`main + 287 at Factorial.swift:7
frame #2: 0x00007fff890be5ad libdyld.dylib`start + 1
frame #3: 0x00007fff890be5ad libdyld.dylib`start + 1
Use o comando continue
(c
) para continuar o processo até que o breakpoint seja encontrado novamente.
(lldb) c
Process 40246 resuming
Process 40246 stopped
* thread #1: tid = 0x14e393, 0x0000000100000e7c Factorial`Factorial.factorial (n=3) -> Swift.Int + 12 at Factorial.swift:2, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x0000000100000e7c Factorial`Factorial.factorial (n=3) -> Swift.Int + 12 at Factorial.swift:2
1 func factorial(n: Int) -> Int {
-> 2 if n <= 1 { return n }
3 return n * factorial(n: n - 1)
4 }
5
6 let number = 4
7 print("\(number)! is equal to \(factorial(n: number))")
Use o comando print
(p
) novamente para inspecionar o valor do parâmetro n
na segunda chamada à função factorial(n:)
.
(lldb) p n
(Int) $R2 = 3
Use o comando breakpoint disable
(br di
) para remover todos os breakpoints e o comando continue
(c
) para que o processo seja executado até o fim, sem mais interrupções.
(lldb) br di
All breakpoints disabled. (1 breakpoints)
(lldb) c
Process 40246 resuming
4! is equal to 24
Process 40246 exited with status = 0 (0x00000000)
Agora que você foi introduzido ao REPL, sistema de compilação e depurador, seguem algumas sugestões para você seguir:
- Cheque a página do projeto do Package Manager para ir mais fundo no sistema de compilação do Swift e no gerenciamento de pacotes.
- Leia Contributing to Swift para descobrir as diversas maneiras de você poder participar da comunidade do Swift.
- Vá para developer.apple.com/swift para obter recursos adicionais relacionados ao Swift, incluindo vídeos, exemplo de código e and playgrounds.