Dado o seguinte em Swift:
var optionalString: String?
let dict = NSDictionary()
Qual é a diferença prática entre as duas declarações a seguir:
optionalString = dict.objectForKey("SomeKey") as? String
vs
optionalString = dict.objectForKey("SomeKey") as! String?
swift
optional
downcast
optional-variables
sdduursma
fonte
fonte
Respostas:
A diferença prática é esta:
optionalString
será uma variável do tipoString?
. Se o tipo subjacente for diferente de um,String
isso será apenas atribuídonil
ao opcional sem causar danos .Isso diz, eu sei que essa coisa é a
String?
. Isso também resultará emoptionalString
ser do tipoString?
, mas travará se o tipo subjacente for outra coisa.O primeiro estilo é então usado
if let
para desembrulhar com segurança o opcional:fonte
as? Types
- significa que o processo de fundição é opcional. O processo pode ser bem-sucedido ou não (o sistema retornará zero se o downcast falhar). Qualquer forma não irá travar se o downcast falhar.as! Type?
- Aqui o processo de down casting deve ser bem sucedido (!
indica que). O ponto de interrogação final indica se o resultado final pode ser nulo ou não.Mais informações sobre "!" e "?"
Vamos pegar 2 casos
Considerar:
Aqui não sabemos se o resultado do downcast de célula com identificador "Cell" para UITableViewCell foi bem-sucedido ou não. Se malsucedido, ele retorna nulo (para evitar travamento aqui). Aqui podemos fazer conforme indicado abaixo.
Portanto, vamos lembrar assim - se
?
isso significa que não temos certeza se o valor é nulo ou não (o ponto de interrogação surge quando não sabemos as coisas).Compare isso com:
Aqui dizemos ao compilador que a conversão deve ser bem-sucedida. Se falhar, o sistema irá travar. Portanto, damos
!
quando temos certeza de que o valor não é nulo.fonte
Para esclarecer o que vacawama disse, aqui está um exemplo ...
Swift 3.0:
Swift 2.0:
fonte
intNil as! String? // ==nil
não causa travamento !!! ???, como Opcional <Int> .Nenhum é diferente de Opcional <String> .Nenhumas?
paraString
? Por que você não reduz paraString?
? Por que você não se abaixaas!
paraString
?Any
vez deAnyObject
as
usado para upcasting e conversão de tipo para tipo com ponteas?
usado para fundição segura, retorna nulo se falharas!
usado para forçar o lançamento, travar se falharNota:
as!
não pode converter o tipo bruto para opcionalExemplos:
Exemplo
Adicionando um ?imediatamente após o tipo de dados, você informa ao compilador que a variável pode conter um número ou não. Arrumado! Observe que realmente não faz sentido definir constantes opcionais - você pode definir seu valor apenas uma vez e, portanto, seria capaz de dizer se seu valor será nulo ou não.
Quando devemos usar "?" e quando "!"
digamos que temos um aplicativo simples baseado em UIKit. temos algum código em nosso controlador de visualização e queremos apresentar um novo controlador de visualização em cima dele. e precisamos decidir empurrar a nova visualização na tela usando o controlador de navegação.
Como sabemos, cada instância de ViewController possui um controlador de navegação de propriedade. Se você estiver construindo um aplicativo baseado em controlador de navegação, esta propriedade do controlador de visualização mestre do seu aplicativo é definida automaticamente e você pode usá-lo para enviar ou abrir controladores de visualização. Se você usar um único modelo de projeto de aplicativo - não haverá um controlador de navegação criado automaticamente para você, então o controlador de visualização padrão do seu aplicativo não terá nada armazenado na propriedade navigationController.
Tenho certeza de que você já adivinhou que este é exatamente o caso de um tipo de dados opcional. Se você marcar UIViewController, verá que a propriedade está definida como:
Portanto, vamos voltar ao nosso caso de uso. Se você sabe com certeza que seu controlador de visualização sempre terá um controlador de navegação, você pode ir em frente e forçar o desempacotamento:
Quando você coloca um! por trás do nome da propriedade, você diz ao compilador que não me importo se esta propriedade é opcional, eu sei que quando este código for executado sempre haverá um armazenamento de valor, portanto, trate este opcional como um tipo de dados normal. Bem, isso não é bom? O que aconteceria se não houvesse um controlador de navegação para o controlador de visualização? Se você sugeriu que sempre haverá um valor armazenado no navigationController estava errado? Seu aplicativo irá falhar. Simples e feio assim.
Que tal se você não tem certeza de que sempre haverá um controlador de navegação? Então você pode usar? em vez de um !:
O que ? por trás do nome da propriedade diz ao compilador que não sei se esta propriedade contém nil ou um valor, então: se ela tiver valor, use-a e, caso contrário, considere a expressão inteira nil.Efetivamente, o? permite que você use essa propriedade apenas no caso de haver um controlador de navegação. Não se verifica de qualquer tipo ou fundições de qualquer tipo. Esta sintaxe é perfeita quando você não se importa se tem um controlador de navegação ou não, e deseja fazer algo apenas se houver.
Muito obrigado a Fantageek
fonte
São duas formas diferentes de Downcasting em Swift.
(
as?
) , que é conhecido como a Forma condicional , retorna um valor opcional do tipo para o qual você está tentando fazer o downcast.(
as!
) , que é conhecida como a Forma Forçada , tenta fazer o downcast e desembrulhar o resultado como uma única ação composta.Para obter mais detalhes, consulte a seção Tipo de fundição da documentação da Apple.
fonte
Talvez este exemplo de código ajude alguém a entender o princípio:
fonte
O primeiro é uma "conversão condicional" (procure em "operadores de conversão de tipo" na documentação que vinculei) . Se a conversão for bem-sucedida, o valor da expressão será agrupado em um opcional e retornado, caso contrário, o valor retornado será nulo.
O segundo significa que optionalString pode ser um objeto string ou pode ser nulo.
Mais informações encontradas nesta questão relacionada .
fonte
Pode ser mais fácil lembrar o padrão para esses operadores no Swift, pois:
!
implica "isso pode interceptar", enquanto?
indica "isso pode ser nulo."consulte: https://developer.apple.com/swift/blog/?id=23
fonte
Eu sou novato em Swift e escrevo este exemplo tentando explicar como eu entendo sobre 'opcionais'. Se eu estiver errado, por favor me corrija.
Obrigado.
(1):
obj.lastName = obj.lName as! String
vs
(2):
obj.lastName = obj.lName as? String
Resposta: (1) Aqui o programador tem certeza absoluta de que
“obj.lName”
contém o objeto do tipo string. Portanto, apenas dê esse valor para“obj.lastName”
.Agora, se o programador estiver correto, significa que
"obj.lName"
é um objeto do tipo string, então não há problema. "obj.lastName" será definido com o mesmo valor.Mas se o programador estiver errado, significa que
"obj.lName"
não é um objeto do tipo string, ou seja, contém algum outro tipo de objeto como "NSNumber" etc. Então CRASH (Erro de tempo de execução).(2) O programador não tem certeza se
“obj.lName”
contém o objeto do tipo string ou qualquer outro objeto de tipo. Portanto, defina esse valor para“obj.lastName”
se for do tipo string.Agora, se o programador estiver correto, significa que
“obj.lName”
é um objeto do tipo string, então não há problema.“obj.lastName”
será definido com o mesmo valor.Mas se o programador estiver errado, significa que obj.lName não é um objeto do tipo string, ou seja, contém algum outro objeto de tipo, como
"NSNumber"
etc. Então“obj.lastName”
será definido com o valor nulo. Então, sem falha (feliz :)fonte