Swift: Condicionais do Swift
As condicionais permitem que seu programa reaja de forma diferente a diferentes situações, assim como um semáforo muda os sinais com base no tráfego. Esta lição aborda todos os mecanismos de controle condicional no Swift: if-else, switch e mais.
1. O Que Você Vai Aprender
- Usar if / else if / else para lógica de ramificação
- Usar switch para correspondência de múltiplos valores e correspondência de padrões
- Usar operadores de intervalo
...e..<para simplificar condições de intervalo - Usar fallthrough para queda entre casos do switch
- Usar a cláusula where para adicionar restrições extras às condições
2. Uma História Real: Um Desenvolvedor Back-End
(1) O Problema: Permissões Baseadas em Funções com Múltiplas Camadas Transformaram o Código em Espaguete
Bob está construindo um sistema de permissões de usuário em uma empresa SaaS. O sistema tem 5 funções de usuário (admin / editor / visualizador / convidado / banido), cada uma com diferentes níveis de acesso a mais de 20 endpoints de API. Bob inicialmente usou 15 camadas de if-else aninhados:
if role == "admin" {
if action == "delete" {
// allow
} else if action == "edit" {
// allow
}
} else if role == "editor" {
// 700 lines of repeated code...
}
O código rapidamente cresceu para mais de 700 linhas. Adicionar uma nova função significava modificar 5 lugares diferentes. Bob passou uma semana inteira corrigindo uma vulnerabilidade de segurança causada pela ordenação incorreta do if-else.
(2) A Solução: switch
Bob refatorou o sistema de permissões usando instruções switch:
let role = "editor"
switch role {
case "admin":
print("Full access granted")
case "editor":
print("Read and write access")
case "viewer", "guest":
print("Read-only access")
case "banned":
print("Access denied")
default:
print("Unknown role")
}
(3) O Resultado: Código Reduzido em 80%, Lógica Ficou Cristalina
| Dimensão | if-else com 15 Camadas | Após Refatoração com switch |
|---|---|---|
| Linhas de código | 700+ | 150 |
| Tempo para adicionar nova função | 30 minutos | 3 minutos |
| Erros de lógica | 3 por mês | 0 por mês |
| Pontuação de legibilidade | 3/10 | 9/10 |
3. Instruções Condicionais if/else
if/else é a estrutura de controle condicional mais fundamental do Swift. Ela decide qual bloco de código executar com base em um valor Bool.
graph TB
A[Condição] -->|true| B[bloco if]
A -->|false| C[bloco else if / else]
B --> D[Continuar]
C --> D
| Sintaxe | Descrição | Exemplo |
|---|---|---|
| if condicao { } | Executa quando a condição é verdadeira | if nota >= 60 { } |
| if ... else { } | Executa else quando a condição é falsa | if ... else { } |
| if ... else if ... else { } | Verifica múltiplas condições em ordem | if ... else if ... else { } |
(1) if e else Básicos
let temperature = 30
if temperature > 25 {
print("It's hot outside")
} else {
print("It's cool outside")
}
(2) Múltiplas Condições com else if
let score = 85
if score >= 90 {
print("Grade: A")
} else if score >= 80 {
print("Grade: B")
} else if score >= 70 {
print("Grade: C")
} else if score >= 60 {
print("Grade: D")
} else {
print("Grade: F")
}
▶ Exemplo: Verificação de Status de Login
// ============================================
// Display different messages based on login status
// ============================================
let isLoggedIn = true
let hasProfile = false
if isLoggedIn {
print("Welcome back!")
if hasProfile {
print("Your profile is complete")
} else {
print("Please complete your profile")
}
} else {
print("Please log in first")
}
Saída:
TEXT 📖 Somente leituraWelcome back! Please complete your profile
4. Correspondência Multi-Ramo com switch
switch é uma ferramenta de correspondência multi-ramo mais poderosa que if-else. O switch do Swift não requer break — a execução sai automaticamente após uma correspondência.
graph TB
A[Valor] --> B[case 1]
A --> C[case 2]
A --> D[case 3]
A --> E[default]
B --> F[Executar e Sair]
C --> F
D --> F
E --> F
| Característica | switch do Swift | switch do C / Java |
|---|---|---|
| break implícito | Automático (não precisa de break) | Deve escrever break |
| Correspondência de intervalo | Suporta ... e ..< |
Não suportado |
| Correspondência composta | Valores separados por vírgula | Depende de fallthrough |
| Exaustivo | Deve cobrir todas as possibilidades | Não aplicado |
| Ramo default | Usa default | Usa default |
(1) Sintaxe Básica do switch
let fruit = "apple"
switch fruit {
case "apple":
print("It's an apple")
case "banana":
print("It's a banana")
case "orange":
print("It's an orange")
default:
print("Unknown fruit")
}
(2) Correspondência de Intervalo e Correspondência Composta
let age = 25
switch age {
case 0..<13:
print("Child")
case 13..<20:
print("Teenager")
case 20..<65:
print("Adult")
case 65...:
print("Senior")
default:
print("Invalid age")
}
▶ Exemplo: Tratamento de Códigos de Status HTTP
// ============================================
// Handle HTTP response status codes with switch
// ============================================
let statusCode = 404
switch statusCode {
case 100..<200:
print("Informational")
case 200..<300:
print("Success")
case 300..<400:
print("Redirection")
case 400..<500:
print("Client error")
if statusCode == 404 {
print("Resource not found")
}
case 500..<600:
print("Server error")
default:
print("Unknown status code")
}
Saída:
TEXT 📖 Somente leituraClient error Resource not found
5. Controle Avançado: fallthrough, where e o Operador Ternário
O Swift fornece ferramentas adicionais para tornar a lógica condicional mais flexível.
| Ferramenta | Finalidade | Exemplo |
|---|---|---|
| fallthrough | Cair para o próximo caso no switch | case "a": fallthrough |
| where | Adicionar filtragem extra a uma condição | case let x where x > 10: |
| Ternário ? : | Escolha concisa de um-ou-outro | let max = a > b ? a : b |
(1) fallthrough
let number = 2
switch number {
case 1:
print("One")
case 2:
print("Two")
fallthrough
case 3:
print("Three or fell through from two")
default:
print("Other")
}
(2) Filtragem com Condição where
let point = (x: 3, y: 4)
switch point {
case let (x, y) where x == y:
print("On the diagonal")
case let (x, y) where x > y:
print("X is larger")
case let (x, y) where x < y:
print("Y is larger")
default:
print("On an axis")
}
(3) O Operador Condicional Ternário
let isMember = true
let discount = isMember ? 0.2 : 0.0
print("Discount: \(discount * 100)%")
▶ Exemplo: Calculadora de Desconto de Pedido
// ============================================
// Combine if/switch/ternary to calculate order discounts
// ============================================
let orderTotal = 250.0
let customerTier = "gold"
// Ternary operator: base discount
let baseDiscount = orderTotal > 100 ? 0.05 : 0.0
// switch: membership tier discount
let tierDiscount: Double
switch customerTier {
case "platinum":
tierDiscount = 0.20
case "gold":
tierDiscount = 0.15
case "silver":
tierDiscount = 0.10
default:
tierDiscount = 0.0
}
// if: cap the combined discount
let totalDiscount = baseDiscount + tierDiscount
let finalDiscount = totalDiscount > 0.3 ? 0.3 : totalDiscount
let finalPrice = orderTotal * (1 - finalDiscount)
print("Order total: $\(orderTotal)")
print("Tier: \(customerTier)")
print("Discount: \(Int(finalDiscount * 100))%")
print("Final price: $\(finalPrice)")
Saída:
TEXT 📖 Somente leituraOrder total: $250.0 Tier: gold Discount: 20% Final price: $200.0
6. Exemplo Completo: Sistema de Gerenciamento de Permissões de Usuário
// ============================================
// User permission management system
// Integrates if/switch/where/ternary operators
// ============================================
import Foundation
enum UserRole {
case admin, editor, viewer, guest, banned
}
enum ActionResult {
case granted, denied(String)
}
func checkPermission(role: UserRole, action: String, isOwner: Bool) -> ActionResult {
switch role {
case .banned:
return .denied("Account is banned")
case .admin:
return .granted
case .editor:
if action == "delete" && !isOwner {
return .denied("Only owners can delete")
}
return .granted
case .viewer:
switch (action, isOwner) {
case (_, false):
return .denied("Viewers cannot modify content")
case ("read", true):
return .granted
default:
return .denied("Unknown action")
}
case .guest:
return action == "read" ? .granted : .denied("Guests can only read")
}
}
let testCases = [
(UserRole.admin, "delete", false),
(UserRole.editor, "delete", true),
(UserRole.editor, "delete", false),
(UserRole.viewer, "read", true),
(UserRole.viewer, "write", false),
(UserRole.guest, "read", false),
(UserRole.banned, "read", false)
]
for (role, action, isOwner) in testCases {
let result = checkPermission(role: role, action: action, isOwner: isOwner)
switch result {
case .granted:
print("[GRANTED] \(role) can \(action)")
case .denied(let reason):
print("[DENIED] \(role) cannot \(action) -- \(reason)")
}
}
Saída:
TEXT 📖 Somente leitura[GRANTED] admin can delete [GRANTED] editor can delete [DENIED] editor cannot delete -- Only owners can delete [GRANTED] viewer can read [DENIED] viewer cannot write -- Viewers cannot modify content [GRANTED] guest can read [DENIED] banned cannot read -- Account is banned
❓ Perguntas Frequentes
P: Por que o switch do Swift não precisa de break? R: O switch do Swift sai automaticamente após corresponder a um caso e não cai para o próximo caso. Para cair intencionalmente, você deve escrever explicitamente fallthrough. P: Como devo escolher entre if e switch? R: Use
ifpara 2-3 ramos. Useswitchquando tiver mais de 3 ramos ou precisar de correspondência de intervalo/padrão. O switch impõe o tratamento exaustivo de todas as possibilidades, tornando-o mais seguro que o if. P: Qual é a diferença entre...e..<? R:a...binclui tanto a quanto b (intervalo fechado).a..<binclui a, mas não b (intervalo semiaberto). Por exemplo,1...3inclui 1, 2, 3;1..<3inclui 1, 2. P: O operador ternário prejudica a legibilidade do código? R: Para escolhas simples de um-ou-outro (como atribuições), o ternário é nítido e claro. Ao aninhar operadores ternários ou quando a lógica fica complexa, useif— uma linha muito longa se torna mais difícil de ler. P: O ramo default pode ser omitido? R: Não. O switch do Swift deve ser exaustivo. Se você cobriu todos os casos (por exemplo, todos os casos de um enum), pode omitir o default.
📖 Resumo
- if/else é o controle condicional mais fundamental, melhor para 2-3 ramos
- switch é melhor para 3+ ramos e suporta correspondência de intervalo, correspondência composta e vinculação de valor
- O fallthrough do switch permite cair para o próximo caso, útil para cenários de correspondência sequencial
- A cláusula where adiciona condições extras de filtragem aos casos do switch e laços for
- O operador ternário ? : é melhor para atribuições concisas de um-ou-outro
- O switch do Swift exige tratamento exaustivo, aumentando a segurança do código
📝 Exercícios
- Iniciante: Use if/else para escrever um classificador de temperatura corporal: temp < 36.0 exibe "Baixa", 36.0...37.5 exibe "Normal", > 37.5 exibe "Febre".
- Intermediário: Refatore o exercício iniciante usando switch para também suportar temp < 35.0 exibindo "Perigosamente Baixa". Use sintaxe de correspondência de intervalo.
- Desafio: Crie uma calculadora de taxas de pagamento. Regras de taxa: Cartão de crédito 2.5% (≥R$100: 2.5% - 0.5%), Cartão de débito 1.0% (limitado a R$5), PayPal 3.0% + R$0.30. Implemente com switch + where.