Portuguese (Português) translation by David Batista (you can also view the original English article)
Nos artigos anteriores, você aprendeu alguns dos conceitos básicos da linguagem de programação Swift. Se você já programou antes, tenho certeza que você viu algumas semelhanças com outras linguagens de programação, como Ruby, JavaScript e Objective-C.
Neste artigo, vamos focar no controle de fluxo do Swift. Antes de discutirmos controle de fluxo com mais detalhe, nós precisamos dar uma olhada em um conceito novo para a maioria de vocês, opcionais. Opcionais é outro recurso de segurança do Swift. A princípio, pode parecer chato usar opcionais, mas você vai aprender rapidamente que os opcionais irão tornar seu código mais seguro.
1. Opcionais
Nós já vimos que uma variável deve ser inicializada antes que possa ser usada. Dê uma olhada no exemplo a seguir para entender melhor o que isso significa.
1 |
var str: String |
2 |
|
3 |
str.isEmpty |
Se você está acostumado a trabalhar com strings em Objective-C, então você ficará surpreso que o Swift nos retornará um erro. Vamos ver o que o erro nos informa.



Em muitas linguagens, variáveis têm um valor padrão inicial. Em Objective-C, por exemplo, a string no seguinte trecho de código é igual nil
.
1 |
NSString *newString; |
No entanto, o conceito do nil
difere em Swift e Objective-C. Vamos discutir nil
com mais detalhes um pouco mais tarde.
O que é um opcional?
Swift usa os opcionais para encapsular um conceito importante, isto é, uma variável ou constante tem um valor ou não tem. É simples assim em Swift. Para declarar uma variável ou constante como opcional, acrescentamos um ponto de interrogação no tipo da variável ou constante.
1 |
var str: String? |
A variável str
não é mais do tipo String
. Agora é do tipo String
opcional. Isso é importante entender. O resultado ou efeito é que não podemos mais interagir diretamente com o valor da variável str
. O valor é armazenado com segurança no opcional e precisamos perguntar ao opcional pelo valor que ele encapsula.
Forçando o desempacotamento (Forced Unwrapping)
Uma forma de acessar o valor de um opcional é através do desempacotamento forçado. Podemos acessar o valor da variável str
, acrescentando um !
no nome da variável.
1 |
var str: String? |
2 |
|
3 |
str = "Test" |
4 |
|
5 |
println(str!) |
É importante que você tenha certeza que o opcional tenha um valor quando você forçar o desempacotamento. Se o opcional não tiver um valor e você forçar o desempacotamento, o Swift retornará um erro para você.



Optional binding
Há uma maneira mais segura para acessar o valor de um opcional. Daremos uma olhada mais atenta na instrução if
em poucos minutos, mas o exemplo a seguir mostra como podemos acessar com segurança o valor armazenado na variável str
, que é do tipo String
opcional.
1 |
var str: String? |
2 |
|
3 |
if str != nil { |
4 |
println(str!) |
5 |
} else { |
6 |
println("str has no value") |
7 |
}
|
Primeiro verificamos se a variável str
é igual nil
antes de imprimir seu conteúdo. Neste exemplo, str
não tem um valor, o que significa que não será forçado o desempacotamento por acidente.
Há uma abordagem mais elegante chamada optional binding. No exemplo a seguir, podemos atribuir o valor armazenado no opcional a uma constante temporária, que é usada na instrução if
. O valor do opcional str
é ligado à constante strConst
e usado na instrução if
. Essa abordagem também funciona em instruções while
.
1 |
var str: String? |
2 |
|
3 |
str = "Test" |
4 |
|
5 |
if let strConst = str { |
6 |
println(strConst) |
7 |
} else { |
8 |
println("str has no value") |
9 |
}
|
O que é nil
?
Se você está vindo do Objective-C, você certamente sabe o que é o nil
. Em Objective-C, nil
é um ponteiro para um objeto que não existe. O Swift define nil
de uma forma um pouco diferente e é importante que você entenda a diferença.
Em Swift, nil
significa a falta de valor, nenhum valor. Enquanto o nil
só é aplicável aos objetos em Objective-C, em Swift nil
pode ser usado em qualquer tipo. Portanto, é importante entender que um opcional não é o equivalente de nil
em Objective-C. Estes conceitos são muito diferentes.
2. Controle de fluxo
O Swift oferece uma quantidade de construtores comuns para controlar o fluxo do seu código. Se você tem alguma experiência de programação, então você não terá problemas em ganhar tempo com os construtores de controle de fluxo do Swift, instruções condicionais if
e switch
, e laços for
e while
.
No entanto, Swift não seria Swift se seus controles de fluxo não fossem um pouco diferente de, por exemplo, construtores de controle de fluxo do Objective-C. Embora os detalhes sejam importantes, eu tenho certeza que eles não vão impedir de ganhar tempo com Swift. Vamos começar com o construtor condicional mais comum, a instrução if
.
if
As instruções if
em Swift são muito similares as existentes em Objective-C. A principal diferença é que não há necessidade em manter a condição entre parênteses. As chaves, no entanto, são obrigatórias. O último impede os desenvolvedores de inserir erros comuns que estão relacionados a escrever if
sem chaves. Isto é como uma instrução if
se parece em Swift.
1 |
let a = 10 |
2 |
|
3 |
if a > 10 { |
4 |
println("The value of \"a\" is greater than 10.") |
5 |
} else { |
6 |
println("The value of \"a\" is less than or equal to 10.") |
7 |
}
|
E não deve ser surpresa que Swift também define uma cláusula else
. O código na clausura else
é executado se a condição for igual a false
. Também é possível encadear declarações if
como mostrado no exemplo a seguir.
1 |
let a = 10 |
2 |
|
3 |
if a > 10 { |
4 |
println("The value of \"a\" is greater than 10.") |
5 |
} else if a > 5 { |
6 |
println("The value of \"a\" is greater than 5.") |
7 |
} else { |
8 |
println("The value of \"a\" is less than or equal to 5.") |
9 |
}
|
Há uma observação importante a se fazer, a condição da instrução if
precisa retornar true
ou false
. Isso não é necessário em instruções if
de Objective-C. Dê uma olhada na seguinte instrução if
de Objective-C.
1 |
NSArray *array = @[]; |
2 |
|
3 |
if (array.count) { |
4 |
NSLog(@"The array contains one or more items."); |
5 |
} else { |
6 |
NSLog(@"The array is empty."); |
7 |
}
|
Se fôssemos transformar o trecho de código acima em Swift, receberiamos um erro. O erro não é muito informativo, mas o Swift nos diz que precisamos garantir que o resultado da condição seja true
ou false
.



A maneira correta de traduzir o trecho acima do Objective-C para Swift é certificando que a condição da instrução if
retorne true
ou false
, como no trecho a seguir.
1 |
let array = [String]() |
2 |
|
3 |
if array.count > 0 { |
4 |
println("The array contains one or more items.") |
5 |
} else { |
6 |
println("The array is empty.") |
7 |
}
|
switch
A instrução switch
de Swift é mais poderosa do que seu equivalente em Objective-C. É também a mais segura que você aprenderá no momento. Embora existam algumas diferenças, a instruções switch
no Swift aderem ao mesmo conceito que as de outras linguagens de programação, um valor é passado para a instrução switch
e é comparado a possíveis padrões correspondentes.
É isso mesmo, padrões. Como eu disse, uma instrução switch
no Swift tem alguns truques na manga. Vamos dar uma olhada nesses truques em instantes. Vamos falar sobre segurança primeiro.
Exaustivo
Uma instrução switch
no Swift precisa ser exaustiva, o que significa que todo valor possível do tipo que entrou para a instrução switch
precisa ser tratado pela instrução switch
. Como em Objective-C, isto é facilmente resolvido adicionando um caso default
, como no exemplo a seguir.
1 |
let a = 10 |
2 |
|
3 |
switch a { |
4 |
case 0: |
5 |
println("a is equal to 0") |
6 |
case 1: |
7 |
println("a is equal to 1") |
8 |
default: |
9 |
println("a has another value") |
10 |
}
|
Fallthrough
Uma diferença importante com a implementação das instruções switch
do Objective-C é a falta de fallthrough implícita. O exemplo a seguir não funciona no Swift por alguns motivos.
1 |
let a = 10 |
2 |
|
3 |
switch a { |
4 |
case 0: |
5 |
case 1: |
6 |
println("a is equal to 1") |
7 |
default: |
8 |
println("a has another value") |
9 |
}
|
O primeiro caso em que a
é comparado com 0
não passa implicitamente para o segundo caso em que a
é comparado com 1
. Se você adicionar o exemplo acima em seu playground, você observará que o Swift mostrará um erro para você. O erro diz que cada caso deve incluir pelo menos uma instrução executável.
Observe que os casos da instrução switch
não incluem instruções break
para sair da instrução switch
. Isso não é necessário em Swift desde o fallthrough implícita não existe na Swift. Isso vai eliminar uma série de erros comuns causados por fallthrough não intencional.
Padrões
O poder de uma instrução switch
no Swift está na correspondência de padrões. Dê uma olhada no exemplo a seguir que usei intervalos para comparar o valor considerado.
1 |
let a = 10 |
2 |
|
3 |
switch a { |
4 |
case 0..<5: |
5 |
println("The value of a lies between 0 and 4.") |
6 |
case 5...10: |
7 |
println("The value of a lies between 5 and 10.") |
8 |
default: |
9 |
println("The value of a is greater than 10.") |
10 |
}
|
O operador ..<
ou operador de intervalo semi-aberto define um intervalo do primeiro para o segundo valor, excluindo o segundo valor. O operador ...
ou operador de intervalo fechado define um intervalo do primeiro para o segundo valor, incluindo o segundo valor. Esses operadores são muito úteis em uma ampla gama de situações.
Você também pode comparar o valor considerado de uma instrução switch
com tuplas. Dê uma olhada no exemplo a seguir para ver como isso funciona.
1 |
let latlng = (34.15, -78.03) |
2 |
|
3 |
switch latlng { |
4 |
case (0, 0): |
5 |
println("We're at the center of the planet.") |
6 |
case (0...90, _): |
7 |
println("We're in the Northern hemisphere.") |
8 |
case (-90...0, _): |
9 |
println("We're in the Southern hemisphere.") |
10 |
default: |
11 |
println("The coordinate is invalid.") |
12 |
}
|
Como você pode ver no exemplo acima, é possível que o valor corresponda a mais de um caso. Quando isso acontece, o primeiro caso correspondente é escolhido. O exemplo acima também ilustra o uso do sublinhado. Como vimos no artigo anterior, podemos usar um caractere de sublinhado, _
, para dizer ao Swift quais valores não estamos interessados.
Ligação de Valor
Ligação de valor também é possível com instruções switch
como o exemplo a seguir demonstra. O segundo valor da tupla é temporariamente ligado à constante description
para o uso no primeiro e segundo caso.
1 |
var response = (200, "OK") |
2 |
|
3 |
switch response { |
4 |
case (200..<400, let description): |
5 |
println("The request was successful with description \(description).") |
6 |
case (400..<500, let description): |
7 |
println("The request was unsuccessful with description \(description).") |
8 |
default: |
9 |
println("The request was unsuccessful with no description.") |
10 |
}
|
for
O laço for
é a primeira instrução de looping que vamos dar uma olhada. Ele se comporta de forma semelhante a laços for
em outras linguagens. Existem duas formas, o de laço for
e o laço for-in
.
for
O laço for
do Swift é quase idêntico a um laço for
em Objective-C, como o exemplo a seguir ilustra. O laço for
executa uma série de instruções até que a condição pré-definida seja cumprida.
1 |
for var i = 0; i < 10; i++ { |
2 |
println("i is equal to \(i).") |
3 |
}
|
Como acontece com a instruções if
, não há nenhuma necessidade de usar parênteses para delimitar a inicialização do laço, condição e a definição de incremento. A instrução do laço, porém, precisa ser delimitada por chaves.
for-in
O laço for-in
é ideal para um looping sobre o conteúdo de um range ou coleções. No exemplo a seguir, nós percorremos os elementos de um array.
1 |
let numbers = [1, 2, 3, 5, 8] |
2 |
|
3 |
for number in numbers { |
4 |
println("number is equal to \(number)") |
5 |
}
|
Também podemos usar os laços for-in
para percorrer os pares chave-valor de um dicionário. No exemplo a seguir, nós declaramos um dicionário e imprimimos o conteúdo no console. Como vimos anteriormente nesta série, a sequência dos pares chave-valor é indefinido já que um dicionário é um conjunto não ordenado de pares chave-valor.
1 |
var bids = ["Tom": 100, "Bart": 150, "Susan": 120] |
2 |
|
3 |
for (name, bid) in bids { |
4 |
println("\(name)'s bid is $\(bid).") |
5 |
}
|
Cada par chave-valor de um dicionário é acessado pelo laço for-in como uma tupla de constantes nomeadas. O laço for-in
é ótimo em combinação com ranges. Tenho certeza que você concorda que o código abaixo é fácil de ler e de compreender graças à utilização de um intervalo fechado.
1 |
for i in 1...10 { |
2 |
println("i is equal to \(i)") |
3 |
}
|
while
O laço while
também vem com duas variações, while
e do-while
. A principal diferença é que o conjunto de instruções de um laço do-while
é sempre executado pelo menos uma vez, por que a condição do do-while
é avaliada no final de cada interação. O exemplo a seguir ilustra está diferença.
1 |
var c = 5 |
2 |
var d = 5 |
3 |
|
4 |
while c < d { |
5 |
println("c is smaller than d") |
6 |
}
|
7 |
|
8 |
do { |
9 |
println("c is smaller than d") |
10 |
} while c < d |
A instrução println
do laço while
nunca será executada enquanto a do laço do-while
é executada uma vez.
Em muitos casos, o laço for
pode ser reescrito como o laço while
e geralmente é o desenvolvedor que determina qual tipo de laço deve usar em uma situação particular. Os seguintes laços for
e while
resulta na mesma saída.
1 |
for var i = 0; i < 10; i++ { |
2 |
println(i) |
3 |
}
|
4 |
|
5 |
var i = 0 |
6 |
|
7 |
while i < 10 { |
8 |
println(i) |
9 |
i++ |
10 |
}
|
Aprenda mais em nosso Curso de Programação em Swift
Se você está interessado em elevar sua educação em Swift para o próximo nível, você pode dar uma olhada no nosso curso completo de desenvolvimento em Swift.
Conclusão
Há muito mais sobre controle de fluxo no Swift do que o que abordamos neste artigo, mas agora você tem uma compreensão básica para continuar sua jornada no Swift. Espero que este tutorial tenha mostrado que a implementação de controles de fluxo do Swift é muito semelhante a outras linguagens de programação, com uma pequena diferença.
No restante desta série, nós vamos fazer mais uso das instruções de controle de fluxo do Swift e você gradualmente obterá uma melhor compreensão das diferenças sutis com linguagens como Objective-C. Na próxima edição desta série, começaremos a explorar funções.
Seja o primeiro a saber sobre novas traduções–siga @tutsplus_pt no Twitter!