iOS - Opcionais em Swift: como utilizar?

iOS - Opcionais em Swift: como utilizar?
Giovanna Moeller
Giovanna Moeller

Compartilhe

Resumindo

Você busca produtividade e segurança em seus códigos em Swift? Então este artigo é para você!

Neste artigo, vamos explorar e compreender as Opcionais do Swift. Veremos também:

  • O que são opcionais e quais os seus benefícios;
  • Como criar e utilizar uma opcional;
  • Como lidar com opcionais de forma segura.

Depois de ler este artigo, você vai conseguir utilizar uma ótima prática para aprimorar a segurança no seu código. Vamos lá?

Banner da Alura em fundo dinâmico azul, sugerindo tecnologia e modernidade para o Quizz Jornada Tech. À esquerda, em letras grandes, 'Quizz Jornada Tech' seguido por 'Teste seus conhecimentos em tecnologia e prepare-se para o próximo nível da sua carreira'. À direita, conectados por uma linha azul suave representando uma trilha, os tópicos: programação, front-end, inteligência artificial, ciência de dados, inovação e gestão. No final da trilha, um botão azul convidando a 'começar agora'. No canto superior direito, o logo da Alura. Clique e inscreva-se já!

O que são opcionais?

Quando você está desenvolvendo um código em Swift, é normal esbarrar com as variáveis opcionais em um determinado momento.

As variáveis opcionais, introduzidas no Swift 4, são uma funcionalidade muito poderosa para garantir maior segurança e produtividade ao código. Mas, o que são opcionais?

Uma variável opcional pode, ou não, conter um valor. Caso não haja um valor, ela será nil, ou seja, nulo (não existe um valor). Se existe um valor, a variável se iguala a esse valor. Veja o exemplo de código abaixo, mas não se preocupe que vamos entender mais pra frente o que tudo isso significa!

var nome: String?
print(nome) // nil

Ou então, se atribuirmos um valor para essa opcional:

var name: String?
name = "Giovanna"
print(name) // Optional("Giovanna")

O uso é bem parecido com variáveis não opcionais, então qual a diferença na prática? Como você pode ver acima, o resultado é a nossa variável "embrulhada" dentro de algo escrito Opcional(). Portanto, precisamos fazer uma verificação, justamente para desembrulhar essa opcional.

Mas, como assim desembrulhar? Vamos imaginar que temos uma caixa, que é nossa opcional. Dentro dessa caixa, pode ter um valor, e quando retiramos o valor de dentro da caixa, a variável se iguala a esse valor. Caso não tenha nada dentro da caixa, então ela nos retornará nil (nothing at all, algo nulo, inexistente).

Ok, mas por que eu iria querer utilizar uma opcional no meu código? Muitas vezes, é a própria linguagem que faz o uso de opcionais para tratar questões de segurança. Vamos ver alguns casos!

Veja abaixo um código onde há a declaração de um array com 4 elementos, e queremos obter o primeiro elemento através da propriedade first:

var numeros: [Int] = [38, 45, 32, 47]
print(numeros.first)

Quando printamos esse código, ele nos retorna uma opcional com o valor dentro em vez de nos retornar o valor literal, veja a imagem abaixo:

A imagem mostra a janela de um Optionals com duas linhas de código. A primeira linha do código é: “var numeros é igual a, abre colchetes, 38, 45, 32, 47 e fecha colchetes. A segunda linha do código é “print, abre parêntesis, numeros.first, fecha parêntesis. Ainda na segunda linha, há uma mensagem com um símbolo de um triângulo que diz, em inglês, “Expression implicitly coerced from ‘Int?’ to ‘Any’. Na parte inferior da imagem, o Swift retorna a informação “Optional, abre parêntesis, 38, fecha parêntesis.

Mas, por que isso acontece? O motivo disso é que o array pode ser vazio inicialmente, então, para evitar que o código quebre, por padrão é utilizado uma opcional. Se o array estiver vazio, não há um primeiro elemento a ser mostrado.

O Swift não sabe exatamente se existe, ou não, um primeiro elemento. Portanto, por questões de segurança, ele nos retorna uma opcional, e é nosso trabalho realizar a verificação dela para averiguar se realmente existe um valor, para então utilizar desse valor sem problemas.

Ok, mas caso o array esteja vazio, o que nos retorna? Nos retorna nil. O nil, como mencionado anteriormente, é a ideia de algo nulo (mas lembre-se que nil não é zero), algo inexistente. Veja a imagem abaixo:

A imagem mostra uma janela de “Optionals” (em português, opcionais), com duas linhas de código e um valor retornado na parte inferior da imagem. A primeira linha de código é: “var numeros, dois pontos, abre colchete, Int, fecha colchete, é igual a um colchete vazio, sem nada preenchido. A segunda linha do código é “print, abre parêntesis, numeros.first, fecha parêntesis. Ainda na segunda linha, há um símbolo de um triângulo em amarelo seguido de uma mensagem que diz “Expression implicitly coerced from ‘Int?’ to ‘Any’. Na parte inferior da imagem, o Swift retorna o valor nil

Um outro exemplo é a conversão de uma String para Int. O Swift nos retorna uma opcional, pois nem toda string pode ser convertida para Int. Veja o exemplo abaixo:

var numero = Int("39")
print(numero) // Optional(39)

Porém, o que acontece se eu tentar converter uma string como "palavra" para int? É impossível, certo?

var numero = Int("palavra")
print(numero) // nil

É por isso que o uso de opcionais é tão importante para a segurança e legibilidade de um código.

Agora que você já sabe o que é uma opcional, provavelmente está se perguntando: "como eu crio uma opcional no meu código"?

Vamos ver a seguir como criar opcionais e verificá-las, para desembrulhá-las da maneira mais segura possível.

Criando uma opcional

Para criar uma variável opcional, precisamos colocar um ponto de interrogação logo depois do tipo da variável, dessa maneira:

var nome: String?
print(nome) // nil

Ou então, se atribuirmos um valor para essa opcional:

var name: String?
name = "Giovanna"
print(name) // Optional("Giovanna")

Variáveis opcionais são muito encontradas em formulários, por exemplo, onde uma informação não é obrigatória, ela é opcional. Ou seja, a informação pode, ou não, conter um valor. Vamos supor que estamos realizando o cadastro de um usuário na nossa aplicação:

struct User {
  var nome: String
  var idade: String
  var email: String
  var telefone: String
  var celular: String?
}

Veja que a variável celular é uma opcional, podemos ou não receber essa informação.

Mas e agora, como fazer para desembrulhar de fato uma opcional? Pois não conseguimos usar o valor que está dentro de uma opcional. Observe o erro que é gerado quando tentamos pegar o primeiro caractere de uma string opcional, com o uso da propriedade first:

var nome: String?
nome = "Giovanna"
print(nome.first)

"Value of optional type 'String?' must be unwrapped to refer to member 'first' of wrapped base type 'String' (em português, “O valor do tipo ‘String’ deve ser desembrulhado para referir o membro 'first' ao tipo ‘String’ embrulhado).

O erro diz que a variável opcional deve ser desembrulhada para retornarmos o primeiro caractere da string. Isso é uma pura questão de segurança, pois o Swift não sabe se há realmente um valor dentro dessa variável opcional.

Ok, então agora que já descobrimos o que são opcionais e como criar uma, vamos aprender a como lidar com elas e desembrulhá-las da maneira mais segura possível.

Lidando com Opcionais

Podemos dizer que existem cinco maneiras que são mais utilizadas para desembrulhar uma opcional, e vamos discutir mais sobre elas aqui:

1) Forçar o desembrulho;

2) Optional Binding;

3) Optional Chaining;

4) Guard let;

5) Nil coalescing operator

Vamos lá?

1) Forçar o desembrulho

Essa é, na verdade, a maneira menos recomendada de lidarmos com uma opcional, pois estamos falando para a linguagem que existe, sim, um valor dentro dela.

Para forçar o desembrulho, nós usamos um ponto de exclamação no final da variável, dessa maneira:

var nome: String?
nome = "Giovanna"
print(nome!)

É preciso ter muito cuidado quando utilizar essa abordagem, pois pode não existir um valor, ou seja, se for nil, a aplicação irá quebrar, causando um runtime error (erro de execução, que é aquele erro que crasha a nossa aplicação). Em todo caso, é sempre recomendado fazer uma verificação se o valor existe ou não. O caso mais seguro de usar o ! para desembrulhar uma opcional é realizar uma verificação para ver se o valor realmente não é nil, dessa maneira:

var nome: String?
nome = "Giovanna"

if nome != nil {
  print(nome!)
}

Então, essa é a primeira maneira, a de forçar o desembrulho. Vamos para a próxima?

2) Optional Binding

O método optional binding é uma abordagem bem mais segura para desembrulhar uma opcional. Veja o código abaixo:

var optionalNome: String?
optionalNome = "Giovanna"

if let nome = optionalNome {
  print(nome)
}

Primeiramente, nós criamos uma constante nome que iguala ao valor de optionalNome se essa variável não for nula, ou seja, se ela não for nil.

Imagem que mostra a janela optionals do Swift e possui seis linhas de código e, por último, retorna um valor na parte inferior da imagem. A primeira linha de código é “var optionalNome, dois pontos, String com ponto de interrogação. A segunda linha é “optionalNome é igual a, abre aspas, Giovanna, fecha aspas. A terceira linha não possui código. A quarta linha é “if let nome é igual a optionalNome, espaço, abre uma chave. A quinta linha começa com um espaço, e depois se lê “print(nome), nome está entre parêntesis. Em seguida, a sexta linha possui apenas uma chave, fechando a chave aberta na quarta linha. Por último, o Swift retorna “Giovanna” na parte inferior da imagem

Observe uma coisa interessante: agora, quando printamos a variável nome, ela não retorna mais como Optional(), e sim o seu valor concreto. Isso acontece porque a variável nome é um valor não-opcional. É desembrulhado pela verificação if let.

Um ponto importante é que a variável nome só pode ser utilizada dentro do escopo da verificação. Se tentarmos utilizar essa variável fora do escopo, causará um erro.

var optionalNome: String?
optionalNome = "Giovanna"

if let nome = optionalNome {
  print(nome)
}
print(nome) // error: cannot find 'nome' in scope

Você também pode usar múltiplas opcionais dentro da mesma verificação, dessa maneira:

var optionalNome: String?
var optionalSobrenome: String?
optionalNome = "John"
optionalSobrenome = "Doe"

if let name = optionalName, let sobrenome = optionalSobrenome {
  print(name)
  print(sobrenome)
}

Pronto! Vimos como podemos usar opcionais por meio da maneira Optional Binding.

3) Optional Chaining

Esse método permite que nosso código rode apenas se nossa opcional possuir de fato um valor. Veja o código abaixo para entender melhor o que é o optional chaining:

var nome: String?
nome = "Giovanna"
print(nome?.first)

Criamos uma variável opcional e atribuímos o seu valor para "Giovanna". Se tivermos colocado apenas print(nome.first), a aplicação causará um erro de compilação que já vimos acima. Portanto, esse operador de interrogação (?) é justamente o optional chaining. Ele só irá pegar o primeiro valor da string (através dessa propriedade first), caso a variável nome não seja nulo (nil). Caso contrário, devolve nil.

Porém, veja que, na verdade, o Swift nos retorna o valor dentro de uma Optional(). Por esse motivo, é muito comum combinarmos optional chaining com optional binding. Veja o código abaixo:

var nome: String?
nome = "Giovanna"
if let primeiroCaractere = nome?.first {
  print(primeiroCaractere)
}

Lembrando que chaining vem de encadeamento, então é a ideia de encadear as propriedades para fazer a verificação.

Agora que você já sabe sobre "forcing unwrap" (forçar o desembrulho), "optional chaining" e "optional binding", vamos para os dois últimos métodos mais comum: "guard let" e "null coalescing operator".

4) Guard let

Esse método é muito parecido com o optional binding (que é o uso do if let, que vimos acima). Porém, se a opcional for nula, ele retorna algo. Veja o código abaixo:

func autenticar(nome: String?, senha: String?) {
  guard let nome = nome, let senha = senha else { return }
  print(nome)
  print(senha)
}

autenticar(nome: "John", senha: "1234")

Portanto, se o código retorna alguma coisa, significa que o guard let deve ser usado dentro de uma função. No código acima, caso ambas as variáveis sejam nil, irá sair da função imediatamente, sem ao menos printar os valores. Vamos fazer o teste? Veja abaixo:

func autenticar(nome: String?, senha: String?) {
  guard let nome = nome, let senha = senha else { return }
  print(nome)
  print(senha)
}

autenticar(nome: nil, senha: nil)

Veja que esse método permite utilizar a variável desembrulhada fora do escopo, enquanto isso não é permitido com o uso do if let, como vimos acima. Então, se precisarmos utilizar uma variável em outros lugares, o recomendado é fazer o uso do guard let em vez do if let - esse é o principal benefício desse método de fazer uma opcional!

5) Nil coalescing operator

O Nil Coalescing Operator é um operador que consiste no uso de dois pontos de interrogação: ??. Ele aceita uma expressão à esquerda, que é a variável opcional, e uma expressão à direita, que é o valor que tomará lugar caso a variável opcional for nil. Veja o código abaixo para entender melhor como funciona:

var optionalNome: String?
optionalNome = "Giovanna"
print(optionalNome ?? "Inexistente")

Nesse caso, quando printamos a variável optionalNome, haverá uma verificação. Se a variável for nil, será mostrado no console a string "Inexistente". Caso contrário, será mostrado o seu valor concreto sem o uso do Optional().

var optionalNome: String?
print(optionalNome ?? "Inexistente") // Irá ser mostrado no console "Inexistente"

Conclusão

Nesse artigo, vimos sobre opcionais, como e porquê utilizá-las, além também de como podemos tratá-las para que nossa aplicação funcione de forma segura e como o esperado, sem quebrar o código.

Se você tem interesse em outros artigos ou quer conhecer mais sobre o desenvolvimento iOS, basta me procurar aqui: Linkedin.

Quer saber mais sobre iOS? Confira nosso curso para iniciantes aqui na Alura: Swift parte 1 - Desenvolvendo para iOS no Xcode

Até a próxima!

Giovanna Moeller
Giovanna Moeller

Desenvolvedora de Software e Criadora de Conteúdo @girl.coding

Veja outros artigos sobre Mobile