Swift: Laços do Swift: for-in, while e repeat-while
Os laços permitem que um computador repita a mesma tarefa, como uma linha de montagem de fábrica funcionando sem parar. Esta lição aborda quando e como usar cada tipo de laço no Swift, com práticas recomendadas.
1. O Que Você Vai Aprender
- Percorrer arrays, intervalos e dicionários com for-in
- Repetir a execução com while enquanto uma condição for verdadeira
- Garantir pelo menos uma execução usando repeat-while
- Controlar o fluxo do laço com break e continue
- Sair de laços aninhados usando instruções rotuladas
2. Uma História Real de um Analista de Dados
(1) Problema: Processar manualmente 100 mil linhas de log — dedos quase caindo
Charlie é analista de dados em uma plataforma de e-commerce. Todo dia ele precisa examinar 100.000 linhas de log de servidor para contabilizar taxas de erro, tempos de resposta e padrões de anomalia. Ele começava copiando e colando manualmente linha por linha no Excel:
// The pain: manual line-by-line processing
let logEntry1 = "2026-07-15 10:23:45 [ERROR] DB timeout"
let logEntry2 = "2026-07-15 10:24:01 [INFO] Request completed"
// ... 99,998 more lines to go
Charlie passava 3 horas por dia nessa tarefa repetitiva e sempre deixava passar entradas. Ele precisava de uma ferramenta automatizada para iterar sobre todos os logs.
(2) A Solução com Laço for-in
let logEntries = [
"2026-07-15 10:23:45 [ERROR] DB timeout",
"2026-07-15 10:24:01 [INFO] Request completed",
"2026-07-15 10:25:30 [ERROR] Connection refused"
]
var errorCount = 0
for entry in logEntries {
if entry.contains("[ERROR]") {
errorCount += 1
}
}
print("Found \(errorCount) errors in log")
(3) Resultado: 3 horas reduzidas para 3 segundos
| Métrica | Excel Manual | Automação com Laço |
|---|---|---|
| Tempo para 100 mil linhas | 3 horas | 3 segundos |
| Contagens perdidas/erradas | 5-10 | 0 |
| Reutilizável | Não | Sim (basta mudar o nome do arquivo) |
| Humor do Charlie | Frustrado | Feliz |
3. Laços for-in
for-in é o laço mais usado no Swift. Ele itera sobre uma sequência — arrays, intervalos, dicionários e mais.
graph LR
A[Sequência] --> B[Próximo Elemento]
B --> C[Executar Corpo]
C --> D{Mais Elementos?}
D -->|Sim| B
D -->|Não| E[Continuar]
| Percorrer | Sintaxe | Valor por Iteração |
|---|---|---|
| Array | for item in array |
Elemento |
| Intervalo | for i in 1...5 |
Valor do índice |
| Dicionário | for (chave, val) in dict |
Tupla chave-valor |
| String | for char in string |
Caractere |
| Array indexado | for (i, item) in array.enumerated() |
Tupla (índice, elemento) |
(1) Percorrendo Arrays e Intervalos
// Traverse an array
let fruits = ["apple", "banana", "orange"]
for fruit in fruits {
print("I like \(fruit)")
}
// Traverse a range
for number in 1...5 {
print("Count: \(number)")
}
// Indexed traversal
let colors = ["red", "green", "blue"]
for (index, color) in colors.enumerated() {
print("\(index + 1). \(color)")
}
(2) Percorrendo Dicionários
let scores = ["Alice": 95, "Bob": 82, "Charlie": 78]
for (name, score) in scores {
print("\(name): \(score)")
}
▶ Exemplo: Calculando a Temperatura Média Mensal
// ============================================
// Calculate average from temperature data using for-in
// ============================================
let monthlyTemps = [5.2, 8.1, 12.5, 18.3, 24.1, 30.2,
32.0, 31.5, 27.8, 21.3, 14.2, 8.9]
var total = 0.0
for temp in monthlyTemps {
total += temp
}
let average = total / Double(monthlyTemps.count)
print("Total: \(total) C")
print("Average: \(String(format: "%.1f", average)) C")
Saída:
TEXT 📖 Somente leituraTotal: 234.1 C Average: 19.5 C
4. while e repeat-while
while repete a execução enquanto uma condição for verdadeira — ótimo quando você não sabe o número exato de iterações. repeat-while garante pelo menos uma execução.
graph TB
subgraph "while"
A[Verificar Condição] -->|true| B[Executar Corpo]
B --> A
A -->|false| C[Sair]
end
subgraph "repeat-while"
D[Executar Corpo] --> E[Verificar Condição]
E -->|true| D
E -->|false| F[Sair]
end
| Tipo | Momento da Verificação | Execuções Mínimas | Quando Usar |
|---|---|---|---|
| while | Antes do corpo | 0 | Orientado por condição, pode nunca executar |
| repeat-while | Depois do corpo | 1 | Garantido pelo menos uma vez, ex.: validação de entrada do usuário |
(1) Laço while
var countdown = 5
while countdown > 0 {
print("\(countdown)...")
countdown -= 1
}
print("Liftoff!")
(2) Laço repeat-while
var attempts = 0
var success = false
repeat {
attempts += 1
print("Attempt #\(attempts)...")
success = Int.random(in: 1...10) > 5
} while !success && attempts < 3
print(success ? "Succeeded!" : "Failed after 3 attempts")
▶ Exemplo: Jogo de Adivinhação de Números
// ============================================
// Number guessing game with repeat-while
// ============================================
import Foundation
let target = Int.random(in: 1...20)
var guess = 0
var attempts = 0
print("Guess a number between 1 and 20")
repeat {
attempts += 1
guess = Int.random(in: 1...20)
print("Attempt \(attempts): guessed \(guess)")
if guess < target {
print(" Too low")
} else if guess > target {
print(" Too high")
} else {
print(" Correct!")
}
} while guess != target
print("Solved in \(attempts) attempts!")
Saída:
TEXT 📖 Somente leituraGuess a number between 1 and 20 Attempt 1: guessed 7 Too low Attempt 2: guessed 15 Too high Attempt 3: guessed 12 Correct! Solved in 3 attempts!
5. break, continue e Instruções Rotuladas
break sai imediatamente de um laço. continue pula a iteração atual e avança para a próxima. Instruções rotuladas permitem saltar para fora de múltiplos laços aninhados.
| Instrução | Efeito | Caso de Uso |
|---|---|---|
break |
Encerra o laço atual imediatamente | Saída antecipada quando o alvo é encontrado |
continue |
Pula a iteração atual, avança para a próxima | Filtrar elementos indesejados |
break <rotulo> |
Sai do laço rotulado nomeado | Sair de laços aninhados |
continue <rotulo> |
Pula para a próxima iteração do laço nomeado | Controle de fluxo em laços aninhados |
(1) break e continue
let numbers = [3, 7, 1, 9, 4, 6, 8]
// break: exit when first even number found
for num in numbers {
if num.isMultiple(of: 2) {
print("Found first even: \(num)")
break
}
}
// continue: only print odd numbers
for num in numbers {
if num.isMultiple(of: 2) {
continue
}
print("Odd: \(num)")
}
(2) Instruções Rotuladas
// Breaking out of multiple loops with a label
outerLoop: for i in 1...5 {
for j in 1...5 {
let product = i * j
if product == 12 {
print("Found: \(i) x \(j) = \(product)")
break outerLoop
}
}
}
▶ Exemplo: Filtragem e Análise de Log
// ============================================
// Processing log data with break/continue
// ============================================
let logEntries = [
"INFO Server started",
"ERROR Database connection failed",
"DEBUG Cache hit ratio 85%",
"ERROR Timeout after 30s",
"INFO Request completed in 120ms",
"ERROR Disk space low"
]
var errorCount = 0
for entry in logEntries {
if entry.hasPrefix("DEBUG") {
continue
}
if entry.hasPrefix("ERROR") {
errorCount += 1
print("[ERROR #\(errorCount)] \(entry)")
}
if errorCount >= 5 {
print("ALERT: Too many errors!")
break
}
}
print("Processed \(logEntries.count) entries, found \(errorCount) errors")
Saída:
TEXT 📖 Somente leitura[ERROR #1] ERROR Database connection failed [ERROR #2] ERROR Timeout after 30s [ERROR #3] ERROR Disk space low Processed 6 entries, found 3 errors
6. Exemplo Completo: Ferramenta de Análise de Log em Lote
// ============================================
// Log analysis tool
// Combining for-in / while / break / continue
// ============================================
import Foundation
let logs = [
"[INFO] 2026-07-15 08:00:00 Server started",
"[ERROR] 2026-07-15 08:05:23 DB connection timeout",
"[INFO] 2026-07-15 08:10:45 Cache warmed up",
"[ERROR] 2026-07-15 08:15:30 Disk I/O error",
"[WARN] 2026-07-15 08:20:00 Memory usage 85%",
"[ERROR] 2026-07-15 08:25:10 Request failed: timeout",
"[INFO] 2026-07-15 08:30:00 Health check OK",
"[DEBUG] 2026-07-15 08:35:00 Query plan: index scan",
"[ERROR] 2026-07-15 08:40:00 Connection pool exhausted"
]
var stats = (info: 0, warn: 0, error: 0, debug: 0)
var errorLines: [String] = []
for entry in logs {
if entry.hasPrefix("[DEBUG]") {
stats.debug += 1
continue
}
if entry.hasPrefix("[ERROR]") {
stats.error += 1
errorLines.append(entry)
} else if entry.hasPrefix("[WARN]") {
stats.warn += 1
} else if entry.hasPrefix("[INFO]") {
stats.info += 1
}
}
print("=== Log Analysis Report ===")
print("Total entries: \(logs.count)")
print("INFO: \(stats.info) | WARN: \(stats.warn) | ERROR: \(stats.error) | DEBUG: \(stats.debug)")
if stats.error > 0 {
print("\n=== Error Details ===")
var i = 0
while i < errorLines.count {
print("\(i + 1). \(errorLines[i])")
i += 1
}
print("\nError rate: \(Double(stats.error) / Double(logs.count) * 100)%")
}
Saída:
TEXT 📖 Somente leitura=== Relatório de Análise de Log === Total de entradas: 9 INFO: 3 | AVISO: 1 | ERRO: 4 | DEBUG: 1 === Detalhes dos Erros === 1. [ERRO] 2026-07-15 08:05:23 Timeout na conexão BD 2. [ERRO] 2026-07-15 08:15:30 Erro de E/S no disco 3. [ERRO] 2026-07-15 08:25:10 Requisição falhou: timeout 4. [ERRO] 2026-07-15 08:40:00 Pool de conexões esgotado Taxa de erro: 44.4%
❓ Perguntas Frequentes
P: Como escolher entre for-in e while? R: Use for-in quando souber o que está iterando (arrays, intervalos etc.). Use while quando o número de iterações for desconhecido e orientado por condição. Use repeat-while quando precisar de pelo menos uma execução. P: O índice de enumerated() começa em 0 ou 1? R: Começa em 0. Se quiser exibir a partir de 1, basta adicionar 1 ao imprimir. P: Qual é a diferença real entre while e repeat-while? R: while verifica a condição antes de executar o corpo — pode executar zero vezes. repeat-while executa o corpo primeiro e depois verifica — garantido pelo menos uma execução. P: Qual é a diferença entre break e continue? R: break encerra todo o laço. continue pula a iteração atual e avança para a próxima. Analogia: break é sair do cinema; continue é pular uma cena chata, mas ficar para assistir o resto. P: Há restrições quanto aos nomes dos rótulos? R: Nomes de rótulos são identificadores personalizados. Convencionalmente, use nomes significativos como
lacoExternooulacoLinha, seguidos por dois pontos, colocados antes doforouwhile.
📖 Resumo
- for-in é o laço mais comum do Swift, usado para percorrer arrays, intervalos, dicionários e outras sequências
- while é adequado para laços orientados por condição que podem executar zero vezes
- repeat-while garante que o corpo do laço execute pelo menos uma vez
- break sai imediatamente do laço atual; continue pula o resto da iteração atual
- Instruções rotuladas permitem sair ou pular vários níveis de laços aninhados
- enumerated() fornece tanto o índice quanto o elemento em um laço for-in
📝 Exercícios
- Iniciante: Use for-in para iterar de 1 a 10 e imprimir o quadrado de cada número (ex.: "O quadrado de 2 é 4").
- Intermediário: Use while para implementar um contador simples: comece de 100 e subtraia 7 a cada vez, imprimindo o valor de cada etapa até que o número seja menor que 0.
- Desafio: Escreva um programa de laço aninhado que gere uma tabuada 9x9. Use instruções rotuladas e break/continue para controlar a formatação da saída (ex.: pular linhas de múltiplos de 5).