Você já viu um monte de códigos no Swift com "?" e "!" e fica perdido? Usa esses operadores mas sem saber direito quando e onde usar? Esse post então é pra você.
O que é um "?" no Swift
O símbolo "?" representa um opcional no Swift. E um opcional é (pasmem) um enum: .Some(Valor Encapsulado) e .None. Isso permite que ele possa ser vazio (.None) ou possa ter algum valor internamente (.Some(valor).
Exemplo:
var x: Int? = 10
Ao criar uma variável com "?", no caso Int? o Swift cria um enum do tipo Optional mas com o estado .Some(10).
var x: Int? = nil
Caso contrário, se você atribui nil, é criada uma variável do tipo Optional com o estado .None
Comparação
Sabendo agora como é armazenado um Opcional, o Swift oferece algumas formas de trabalhar com ele. Podemos comparar ele de algumas formas:
let x: Int? = 10
switch x{
case .Some(let value) : print("Valor de x \(value)")
case .None : print("x não tem valor")
}
Uma boa prática é "desembrulhar" (do inglês unwrap) o valor da váriavel de forma segura usando o guard. O guard pode ser executado da seguinte forma:
func foo(x: Int?){
guard let y = x else{
return
}
print(y)
}
Encadeamento Opcional
O encadeamento opcional permite você pegar o valor de dentro de um opcional. Diferente do Unwrapping Forçado que vou falar a seguir, ele não causa um erro caso não tenha um valor dento do Opcional. Vamos ao exemplo:
var x: Int? = 10 // .Some(10)
var y: Int = x? // 10
No exemplo simples acima quando eu chamo x? eu faço um unwrapping do Opcional, ou seja, eu pego somente o valor que existe dentro dele. Vamos para um exemplo um pouco mais complexo. Considere o código:
class Person{
var residence: Residence?
}
class Residence{
var numberOfRooms = 1
}
Agora considere a seguinte função:
func foo(){
let john = Person()
if let roomCount = john.residence?.numberOfRooms{
print("Número de quartos \(roomCount)")
} else {
print("Não foi possível determinar o número de quartos")
}
}
O trecho de código acima não irá produzir um erro, pois o encadeamento opcional sempre retornar um Opcional que pode ser comparado. Mas ele será nil. Então sua condição irá cair no else. Mas se mudarmos aqui:
func foo(){
let john = Person()
john.residence = Residence()
if let roomCount = john.residence?.numberOfRooms{
print("Número de quartos \(roomCount)")
} else {
print("Não foi possível determinar o número de quartos")
}
}
O retorno será 1, pois é o valor padrão da quantidade de quartos.
Unwrapping Forçado
O unwrapping forçado tem uma sintaxe parecida, trocando apenas "?" por "!". Mas ele tem uma diferença fundamental: Caso o valor no Opcional seja nil, é gera um erro de execução e o aplicativo irá encerrar, caso não tratado. Utilizando o exemplo acima:
func foo(){
let john = Person()
if let roomCount = john.residence!.numberOfRooms{ //o app irá quebrar nessa linha
print("Número de quartos \(roomCount)")
} else {
print("Não foi possível determinar o número de quartos")
}
}
o unwrapping forçado só deve ser usado caso você tenha ABSOLUTA CERTEZA de que o Opcional tenha valor.
Coalescência
O operador de coalescência "??" permite que você retorne o primeiro valor não nulo (nil) de duas variáveis. Vamos deixar mais claro no exemplo:
let c: Int? = 10
let d: Int = 0
let e = c ?? d //o valor de e será 10
No exemplo acima prevalece o primeiro valor não nil. Segundo exemplo:
let c: Int? = nil
let d: Int = 5
let e = c ?? d //o valor de e será 5
Como no exemplo acima c é nil, o valor de e será 5, o primeiro valor não nil.
BONUS ADVANCED: Map e FlatMap
O tipo Opcional ainda oferece duas funções chamadas Map e Flatmap que permitem que você controle o método de unwrapping passando um closure. A única diferença entro o Map e Flatmap é que o Map não pode devolver nil. Exemplos, exemplos:
var a : Int? = 10
let y : Int? = a.Map{
if $0 < 10 {
return 0
} else {
return $0
}
}
let z : Int? = a.FlatMap{
if $0 < 10 {
return nil
} else {
return $0
}
}
É isso gente. Esse é todo o "mistério" dos Opcionais no Swift. A partir de agora você já sabe ler quando encontrar "?" e "!" nos códigos e sabe como posicionar nos seus próprios códigos.
Até a próxima! Keep coding!
Top comments (0)