Estou aprendendo o Swift para iOS 8 / OSX 10.10 seguindo este tutorial , e o termo " valor desembrulhado " é usado várias vezes, como neste parágrafo (em Objetos e classe ):
Ao trabalhar com valores opcionais, você pode escrever? antes de operações como métodos, propriedades e assinatura. Se o valor antes do? é nulo, tudo depois do? é ignorado e o valor de toda a expressão é nulo. Caso contrário, o valor opcional é desembrulhado e tudo após o? atua sobre o valor desembrulhado . Nos dois casos, o valor da expressão inteira é um valor opcional.
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
Não entendi e procurei na web sem sorte.
O que isso significa?
Editar
Da resposta de Cezary, há uma pequena diferença entre a saída do código original e a solução final (testada no playground):
Código original
Solução de Cezary
As propriedades da superclasse são mostradas na saída no segundo caso, enquanto há um objeto vazio no primeiro caso.
O resultado não deveria ser idêntico nos dois casos?
Perguntas e respostas relacionadas: O que é um valor opcional no Swift?
Respostas:
Primeiro, você precisa entender o que é um tipo opcional. Um tipo opcional basicamente significa que a variável pode ser
nil
.Exemplo:
O ponto de interrogação indica o fato que
canBeNil
pode sernil
.Isso não funcionaria:
Para obter o valor da sua variável, se for opcional, você deve desembrulhá-lo . Isso significa apenas colocar um ponto de exclamação no final.
Seu código deve ficar assim:
Uma nota lateral:
Você também pode declarar opcionais para desembrulhar automaticamente usando um ponto de exclamação em vez de um ponto de interrogação.
Exemplo:
Portanto, uma maneira alternativa de corrigir seu código é:
EDITAR:
A diferença que você está vendo é exatamente o sintoma do fato de o valor opcional estar quebrado . Há outra camada em cima dela. A versão desembrulhada apenas mostra o objeto reto porque é, bem, desembrulhado.
Uma rápida comparação do playground:
No primeiro e no segundo casos, o objeto não está sendo desembrulhado automaticamente, então você vê duas "camadas" (
{{...}}
), enquanto no terceiro caso, você vê apenas uma camada ({...}
) porque o objeto está sendo desembrulhado automaticamente.A diferença entre o primeiro caso e os segundos dois casos é que os dois segundos casos fornecerão um erro de tempo de execução se
optionalSquare
estiver definido comonil
. Usando a sintaxe no primeiro caso, você pode fazer algo assim:fonte
init()
função da classe. Eu recomendo a leitura dos capítulos "The Basics" (abrange opcionais), "Inicialização" e "Encadeamento opcional" no livro Swift lançado pela Apple.A resposta correta existente é ótima, mas eu achei que para entender isso completamente, eu precisava de uma boa analogia, pois esse é um conceito muito abstrato e estranho.
Então, deixe-me ajudar os colegas desenvolvedores "de cérebro direito" (pensamento visual) dando uma perspectiva diferente, além da resposta correta. Aqui está uma boa analogia que me ajudou muito.
Presente de aniversário
Pense nos opcionais como sendo presentes de aniversário que vêm em embalagens rígidas, duras e coloridas.
Você não sabe se há algo dentro do embrulho até desembrulhar o presente - talvez não haja nada lá dentro! Se houver algo dentro, pode ser outro presente, que também está embrulhado e que também pode não conter nada . Você pode até desembrulhar 100 presentes aninhados para finalmente descobrir que não havia nada além de embalagem .
Se o valor do opcional não for
nil
, agora você revelou uma caixa contendo algo . Mas, especialmente se o valor não for digitado explicitamente e for uma variável e não uma constante predefinida, você ainda precisará abrir a caixa para poder saber algo específico sobre o que está na caixa, como que tipo ou qual é o valor valor real é.O que está na caixa?! Analogia
Mesmo depois de desembrulhar a variável, você ainda é como Brad Pitt na última cena de SE7EN ( aviso : spoilers e linguagem suja e violência muito cotada para R), porque mesmo depois de desembrulhar o presente, você está na seguinte situação: agora você tem
nil
ou uma caixa contendo algo (mas você não sabe o que).Você pode saber o tipo de algo . Por exemplo, se você declarasse a variável como sendo do tipo,
[Int:Any?]
saberia que tinha um Dicionário (potencialmente vazio) com subscritos inteiros que produzem conteúdos agrupados de qualquer tipo antigo.É por isso que lidar com tipos de coleção (dicionários e matrizes) no Swift pode ficar meio peludo.
Caso em questão:
fonte
A Swift atribui um alto valor à segurança do tipo. Toda a linguagem Swift foi projetada com segurança em mente. É uma das marcas registradas da Swift e que você deve receber de braços abertos. Ele ajudará no desenvolvimento de código limpo e legível e ajudará a impedir que seu aplicativo falhe.
Todos os opcionais no Swift são demarcados com o
?
símbolo. Ao definir o?
depois do nome do tipo em que você está declarando como opcional, você basicamente está convertendo isso não como o tipo anterior a?
, mas como o tipo opcional .Usando opcional
Isso não significa que você está trabalhando com um tipo de
String
. Isso significa que você está trabalhando com um tipo deString?
(String Optional ou Optional String). De fato, sempre que você tentaem tempo de execução, o console de depuração será impresso
Optional("foobar")
. AOptional()
parte " " indica que esta variável pode ou não ter um valor em tempo de execução, mas acontece que atualmente está contendo a string "foobar". EstaOptional()
indicação " " permanecerá, a menos que você faça o que é chamado "desembrulhando" o valor opcional.Desembrulhar um opcional significa que agora você está convertendo esse tipo como não opcional. Isso irá gerar um novo tipo e atribuir o valor que residia dentro desse opcional ao novo tipo não opcional. Dessa forma, você pode executar operações nessa variável, pois foi garantido pelo compilador um valor sólido.
O desempacotamento condicional verificará se o valor no opcional é
nil
ou não. Caso contrárionil
, haverá uma variável constante recém-criada, à qual será atribuído o valor e desembrulhado na constante não opcional. E a partir daí você pode usar com segurança o não opcional noif
bloco.Desdobrar condicionalmente os opcionais é a maneira mais limpa de acessar o valor de um opcional, porque se ele contiver um valor nulo, tudo dentro do bloco if let não será executado. Obviamente, como qualquer instrução if, você pode incluir um bloco else
O desembrulhamento forçado é feito empregando o que é conhecido como
!
operador ("bang"). Isso é menos seguro, mas ainda permite que seu código seja compilado. No entanto, sempre que você usa o operador bang, você deve ter 1000% de certeza de que sua variável realmente contém um valor sólido antes de desembrulhar à força.Isso acima é um código Swift totalmente válido. Ele imprime o valor
myString
definido como "foobar". O usuário veriafoobar
impresso no console e é isso. Mas vamos assumir que o valor nunca foi definido:Agora temos uma situação diferente em nossas mãos. Diferentemente do Objective-C, sempre que é feita uma tentativa de desembrulhar à força um opcional, o opcional não foi definido e é
nil
, quando você tenta desembrulhar o opcional para ver o que está dentro do seu aplicativo falhará.Desembrulhando w / Type Casting . Como dissemos anteriormente, enquanto você é
unwrapping
o opcional, na verdade, está convertendo para um tipo não opcional, também pode converter o não opcional para um tipo diferente. Por exemplo:Em algum lugar do nosso código, a variável
something
será definida com algum valor. Talvez estejamos usando genéricos ou talvez exista alguma outra lógica que faça com que isso mude. Portanto, mais tarde em nosso código, queremos usar,something
mas ainda podemos tratá-lo de maneira diferente se for um tipo diferente. Nesse caso, você desejará usar aas
palavra-chave para determinar isso:Observe a diferença entre as duas
as
palavras-chave. Como antes, quando desembrulhamos à força um opcional, usamos o!
operador bang para fazer isso. Aqui você fará a mesma coisa, mas, em vez de lançar como apenas um não opcional, você também estará lançando comoInt
. E deve poder ser abatidoInt
, caso contrário, como usar o operador bang quando o valor fornil
seu aplicativo falhará.E para usar essas variáveis em algum tipo ou operação matemática, elas devem ser desembrulhadas para fazer isso.
Por exemplo, no Swift, apenas tipos de dados de número válido do mesmo tipo podem ser operados um contra o outro. Quando você lança um tipo com
as!
você, está forçando o downcast dessa variável como se tivesse certeza de que é desse tipo, portanto, é seguro operar e não travar seu aplicativo. Tudo bem, desde que a variável seja do tipo para a qual você está lançando, caso contrário, você terá uma bagunça nas mãos.No entanto, a conversão com
as!
permitirá que seu código seja compilado. Fundir com umas?
é uma história diferente. De fato,as?
declara o seuInt
como um tipo de dados completamente diferente.Agora é
Optional(0)
E se você já tentou fazer sua lição de casa escrevendo algo como
Seu professor de matemática provavelmente teria lhe dado um "F". O mesmo com Swift. Exceto que Swift prefere não compilar, em vez de dar uma nota. Porque no final do dia, o opcional pode de fato ser nulo .
Segurança First Kids.
fonte
'?' significa expressão opcional de encadeamento,
o '!' significa valor de força
fonte