Decorações variáveis ​​rápidas com “?” (ponto de interrogação) e “!” (ponto de exclamação)

106

Eu entendo que em Swift todas as variáveis ​​devem ser definidas com um valor e que, usando opcionais, podemos definir uma variável a ser definida nilinicialmente.

O que eu não entendo é o que definir uma variável com um !está fazendo, porque eu estava com a impressão de que isso "desembrulha" um valor de um opcional. Achei que, ao fazer isso, você estaria garantindo que havia um valor a ser desembrulhado nessa variável, que é o motivo pelo qual em IBActions e similares você o vê usado.

Então, simplesmente, para que serve a variável sendo inicializada quando você faz algo assim:

var aShape : CAShapeLayer!

E por que / quando eu faria isso?

Jason Renaldo
fonte
Você faria isso para saber que uma variável não é nula depois de verificar esse fato.
Matthias
Não acho que isso deva ser marcado como uma duplicata. "O que é opcional?" não é a mesma pergunta que "Qual é a diferença entre os dois tipos de opcionais?" que é basicamente o que esta pergunta é
Jiaaro
@Jiaaro, mesmo nesse caso, já existem toneladas de perguntas sobre opcionais, opcionais implicitamente desembrulhados e assim por diante. Você também pode consultar este aqui: stackoverflow.com/questions/24272781/…
Jack
@JackWu Ok, mas tenho quase certeza de que essa pergunta não era uma duplicata quando foi feita. (foi perguntado uma semana inteira antes do seu exemplo, por exemplo)
Jiaaro
@Jiaaro Você fez uma boa observação, não percebi que era mais antigo ... talvez outro deva ser marcado como uma duplicata deste em vez disso ..
Jack

Respostas:

145

Em uma declaração de tipo, o !é semelhante ao ?. Ambos são opcionais, mas o !é um opcional "desembrulhado implicitamente" , o que significa que você não precisa desembrulhar para acessar o valor (mas ainda pode ser nulo).

Esse é basicamente o comportamento que já tínhamos no objetivo-c. Um valor pode ser nulo e você deve verificar por ele, mas você também pode acessar o valor diretamente como se não fosse um opcional (com a importante diferença de que se você não verificar nulo, você obterá um erro de tempo de execução)

// Cannot be nil
var x: Int = 1

// The type here is not "Int", it's "Optional Int"
var y: Int? = 2

// The type here is "Implicitly Unwrapped Optional Int"
var z: Int! = 3

Uso:

// you can add x and z
x + z == 4

// ...but not x and y, because y needs to be unwrapped
x + y // error

// to add x and y you need to do:
x + y!

// but you *should* do this:
if let y_val = y {
    x + y_val
}
Jiaaro
fonte
7
Opcionais implicitamente desembrulhados são descritos em uma seção apropriadamente nomeada começando na página 56 de The Swift Programming Language .
Caleb
@Caleb Eu adicionei um link para a seção relevante dos documentos online onde mencionei opcionais não embrulhados implicitamente :)
Jiaaro
Ótima informação, obrigado. Geralmente amando a segurança que o Swift está nos impondo até agora, deve produzir muito menos bugs :).
Jason Renaldo
@Jiaaro: Muito obrigado por compartilhar. Faz o usuário entender perfeitamente pelo exemplo acima. !! :)
Esha
3
Acho que a frase " Este é basicamente o comportamento que já tínhamos em objetivo-c " pode ser confusa. Em Objective-C pode-se aceder a um nilvalor e realmente "trabalhar" com ele, em rápida acessar um opcional implicitamente desembrulhado Embora seja nula irá lançar uma exceção tempo de execução.
Sascha Wolf