O que é um valor opcional no Swift?


267

Da documentação da Apple :

Você pode usar ife letjuntos para trabalhar com valores que podem estar ausentes. Esses valores são representados como opcionais. Um valor opcional contém um valor ou nilindica que o valor está ausente. Escreva um ponto de interrogação ( ?) após o tipo de um valor para marcar o valor como opcional.

Por que você deseja usar um valor opcional?



1
O opcional também pode ser visto como uma implementação da mônada Option / Maybe . Este blog faz um bom trabalho tentando explicar o que é um conceito difícil.
StuartLC

tldr: "O Swift precisa que você seja claro sobre quando um valor pode estar faltando e quando é garantido que ele existe." da excelente resposta
jonatan

Respostas:


531

Um opcional no Swift é um tipo que pode conter um valor ou nenhum valor. Os opcionais são gravados anexando a ?a qualquer tipo:

var name: String? = "Bertie"

Os opcionais (juntamente com os genéricos) são um dos conceitos Swift mais difíceis de entender. Por causa de como eles são escritos e usados, é fácil ter uma idéia errada do que são. Compare o opcional acima para criar uma String normal:

var name: String = "Bertie" // No "?" after String

A partir da sintaxe, parece que uma String opcional é muito semelhante a uma String comum. Não é. Uma String opcional não é uma String com alguma configuração "opcional" ativada. Não é uma variedade especial de String. Uma String e uma String opcional são tipos completamente diferentes.

Aqui está a coisa mais importante a saber: Um opcional é um tipo de contêiner. Uma String opcional é um contêiner que pode conter uma String. Um Int opcional é um contêiner que pode conter um Int. Pense em um opcional como um tipo de parcela. Antes de abri-lo (ou "desembrulhar" no idioma dos opcionais), você não saberá se ele contém algo ou nada.

Você pode ver como os opcionais são implementados na Swift Standard Library digitando "Opcional" em qualquer arquivo Swift e clicando ⌘ nele. Aqui está a parte importante da definição:

enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}

Opcional é apenas um enumque pode ser um dos dois casos: .noneou .some. Se for .some, existe um valor associado que, no exemplo acima, seria o String"Olá". Um opcional usa Genéricos para atribuir um tipo ao valor associado. O tipo de uma String opcional não é String, é Optionalou mais precisamente Optional<String>.

Tudo o que o Swift faz com os opcionais é mágico para tornar a leitura e a escrita de códigos mais fluentes. Infelizmente, isso obscurece a maneira como realmente funciona. Vou passar por alguns truques mais tarde.

Nota: falarei muito sobre variáveis ​​opcionais, mas também é bom criar constantes opcionais. Marquei todas as variáveis ​​com seus tipos para facilitar a compreensão dos tipos de tipos que estão sendo criados, mas você não precisa fazer isso em seu próprio código.


Como criar opcionais

Para criar um opcional, anexe a ?após o tipo que você deseja agrupar. Qualquer tipo pode ser opcional, até mesmo seus próprios tipos personalizados. Você não pode ter um espaço entre o tipo e o ?.

var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)

// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}

Usando opcionais

Você pode comparar um opcional nilpara ver se ele possui um valor:

var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
    print("There is a name")
}
if name == nil { // Could also use an "else"
    print("Name has no value")
}

Isto é um pouco confuso. Isso implica que um opcional é uma coisa ou outra. É nulo ou é "Bob". Isso não é verdade, o opcional não se transforma em outra coisa. Compará-lo a zero é um truque para tornar o código mais fácil de ler. Se um opcional for igual a zero, isso significa apenas que o enum está atualmente definido como .none.


Somente opcionais podem ser nulos

Se você tentar definir uma variável não opcional como nula, receberá um erro.

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'

Outra maneira de ver os opcionais é como um complemento às variáveis ​​Swift normais. Eles são uma contrapartida de uma variável que é garantida como tendo um valor. Swift é uma linguagem cuidadosa que odeia ambiguidade. A maioria das variáveis ​​é definida como não opcional, mas às vezes isso não é possível. Por exemplo, imagine um controlador de exibição que carrega uma imagem de um cache ou da rede. Pode ou não ter essa imagem no momento em que o controlador de exibição é criado. Não há como garantir o valor da variável de imagem. Nesse caso, você precisaria torná-lo opcional. Inicia como nile quando a imagem é recuperada, o opcional recebe um valor.

O uso de um opcional revela a intenção dos programadores. Comparado ao Objective-C, onde qualquer objeto pode ser nulo, o Swift precisa que você seja claro sobre quando um valor pode estar faltando e quando é garantido que ele existe.


Para usar um opcional, você o "desembrulha"

Um opcional Stringnão pode ser usado no lugar de um real String. Para usar o valor agrupado dentro de um opcional, você deve desembrulhá-lo. A maneira mais simples de desembrulhar um opcional é adicionar um !após o nome opcional. Isso é chamado de "força de desembrulhar". Ele retorna o valor dentro do opcional (como o tipo original), mas se o opcional for nil, causa uma falha no tempo de execução. Antes de desembrulhar, verifique se há um valor.

var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.

Verificando e usando um opcional

Como você sempre deve verificar o valor nulo antes de desembrulhar e usar um opcional, este é um padrão comum:

var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
    let unwrappedMealPreference: String = mealPreference!
    print("Meal: \(unwrappedMealPreference)") // or do something useful
}

Nesse padrão, você verifica se um valor está presente e, quando tiver certeza, é forçado a desembrulhá-lo em uma constante temporária para uso. Como isso é algo comum, o Swift oferece um atalho usando "if let". Isso é chamado de "ligação opcional".

var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
    print("Meal: \(unwrappedMealPreference)") 
}

Isso cria uma constante temporária (ou variável, se você substituir letpor var), cujo escopo está apenas dentro das chaves do if. Como ter que usar um nome como "desempacotadoMealPreference" ou "realMealPreference" é um fardo, o Swift permite reutilizar o nome da variável original, criando um nome temporário no escopo do colchete

var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // separate from the other mealPreference
}

Aqui está um código para demonstrar que uma variável diferente é usada:

var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
    mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"

A ligação opcional funciona verificando se o opcional é igual a zero. Caso contrário, desembrulha o opcional na constante fornecida e executa o bloco. No Xcode 8.3 e posterior (Swift 3.1), tentar imprimir um opcional como esse causará um aviso inútil. Use os opcionais debugDescriptionpara silenciá-lo:

print("\(mealPreference.debugDescription)")

Para que são opcionais?

Os opcionais têm dois casos de uso:

  1. Coisas que podem falhar (eu esperava algo, mas não consegui nada)
  2. Coisas que não são nada agora, mas que podem ser algo mais tarde (e vice-versa)

Alguns exemplos concretos:

  • Uma propriedade que pode estar lá ou não, como middleNameou spouseem uma Personclasse
  • Um método que pode retornar um valor ou nada, como procurar uma correspondência em uma matriz
  • Um método que pode retornar um resultado ou obter um erro e não retornar nada, como tentar ler o conteúdo de um arquivo (que normalmente retorna os dados do arquivo), mas o arquivo não existe
  • Delegar propriedades, que nem sempre precisam ser definidas e geralmente são definidas após a inicialização
  • Para weakpropriedades em classes. O que eles apontam pode ser definido a nilqualquer momento
  • Um grande recurso que talvez precise ser liberado para recuperar a memória
  • Quando você precisar saber como um valor foi definido (dados ainda não carregados> os dados) em vez de usar um dataLoaded separado Boolean

Os opcionais não existem no Objective-C, mas há um conceito equivalente, retornando nulo. Métodos que podem retornar um objeto podem retornar nulo. Isso significa "a ausência de um objeto válido" e é frequentemente usado para dizer que algo deu errado. Ele funciona apenas com objetos Objective-C, não com primitivos ou tipos C básicos (enumerações, estruturas). O Objective-C geralmente tinha tipos especializados para representar a ausência desses valores (o NSNotFoundque é realmente NSIntegerMax, kCLLocationCoordinate2DInvalidpara representar uma coordenada inválida -1ou também é usado algum valor negativo). O codificador precisa conhecer esses valores especiais para que eles sejam documentados e aprendidos para cada caso. Se um método não pode tomar nilcomo parâmetro, isso deve ser documentado. No Objetivo-C,nilera um ponteiro, assim como todos os objetos eram definidos como ponteiros, mas nilapontavam para um endereço (zero) específico. Em Swift, nilé um literal que significa a ausência de um determinado tipo.


Comparando à nil

Você costumava usar qualquer opcional como Boolean:

let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}

Nas versões mais recentes do Swift, você precisa usar leatherTrim != nil. Por que é isso? O problema é que um Booleanpode ser envolvido em um opcional. Se você tem Booleanassim:

var ambiguous: Boolean? = false

ele tem dois tipos de "false", um onde não há valor e outro onde ele tem um valor, mas o valor é false. Swift odeia ambiguidade, então agora você deve sempre verificar um opcional contra nil.

Você pode se perguntar qual é o objetivo de um opcional Boolean? Como com outros opcionais, o .noneestado pode indicar que o valor ainda é desconhecido. Pode haver algo do outro lado de uma chamada de rede que leva algum tempo para ser pesquisado. Booleanos opcionais também são chamados de " Booleanos de Três Valores "


Truques rápidos

O Swift usa alguns truques para permitir que os opcionais funcionem. Considere estas três linhas de código opcional com aparência comum;

var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }

Nenhuma dessas linhas deve compilar.

  • A primeira linha define uma String opcional usando um literal String, dois tipos diferentes. Mesmo se este fosse um, Stringos tipos são diferentes
  • A segunda linha define uma String opcional como nula, dois tipos diferentes
  • A terceira linha compara uma string opcional a zero, dois tipos diferentes

Vou examinar alguns dos detalhes de implementação de opcionais que permitem que essas linhas funcionem.


Criando um opcional

Usar ?para criar um opcional é o açúcar sintático, ativado pelo compilador Swift. Se você quiser fazer isso da maneira mais longa, poderá criar um opcional como este:

var name: Optional<String> = Optional("Bob")

Isso chama Optionalo primeiro inicializador, public init(_ some: Wrapped)que infere o tipo associado do opcional do tipo usado entre parênteses.

A maneira ainda mais longa de criar e definir um opcional:

var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")

Definir um opcional para nil

Você pode criar um opcional sem valor inicial ou criar um com o valor inicial de nil(ambos têm o mesmo resultado).

var name: String?
var name: String? = nil

Permitir que os opcionais sejam iguais nilé ativado pelo protocolo ExpressibleByNilLiteral(nomeado anteriormente NilLiteralConvertible). O opcional é criado com Optionalo segundo inicializador public init(nilLiteral: ()),. Os documentos dizem que você não deve usar ExpressibleByNilLiteralnada além de opcionais, pois isso mudaria o significado de zero no seu código, mas é possível fazer isso:

class Clint: ExpressibleByNilLiteral {
    var name: String?
    required init(nilLiteral: ()) {
        name = "The Man with No Name"
    }
}

let clint: Clint = nil // Would normally give an error
print("\(clint.name)")

O mesmo protocolo permite definir um opcional já criado como nil. Embora não seja recomendado, você pode usar o inicializador literal nulo diretamente:

var name: Optional<String> = Optional(nilLiteral: ())

Comparando um opcional para nil

Os opcionais definem dois operadores "==" e "! =" Especiais, que você pode ver na Optionaldefinição. O primeiro ==permite que você verifique se algum opcional é igual a zero. Dois opcionais diferentes definidos como .none sempre serão iguais se os tipos associados forem os mesmos. Quando você compara com zero, nos bastidores, o Swift cria um opcional do mesmo tipo associado, definido como .none e o utiliza para a comparação.

// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
    print("tuxedoRequired is nil")
}

O segundo ==operador permite comparar dois opcionais. Ambos precisam ser do mesmo tipo e esse tipo precisa estar em conformidade Equatable(o protocolo que permite comparar as coisas com o operador "==" regular). Swift (presumivelmente) desembrulha os dois valores e os compara diretamente. Ele também lida com o caso em que um ou ambos os opcionais estão .none. Observe a distinção entre comparar com o nilliteral.

Além disso, permite comparar qualquer Equatabletipo com uma embalagem opcional desse tipo:

let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}

Nos bastidores, Swift envolve o não opcional como opcional antes da comparação. Também funciona com literais ( if 23 == numberFromString {)

Eu disse que existem dois ==operadores, mas há um terceiro que permite que você coloque nilno lado esquerdo da comparação

if nil == name { ... }

Opcionais de nomeação

Não existe uma convenção Swift para nomear tipos opcionais de maneira diferente dos tipos não opcionais. As pessoas evitam adicionar algo ao nome para mostrar que é opcional (como "optionalMiddleName" ou "possibleNumberAsString") e permitem que a declaração mostre que é um tipo opcional. Isso fica difícil quando você deseja nomear algo para reter o valor de um opcional. O nome "middleName" implica que é um tipo de String, portanto, quando você extrai o valor da String, geralmente pode acabar com nomes como "actualMiddleName" ou "desempacotadoMiddleName" ou "realMiddleName". Use a ligação opcional e reutilize o nome da variável para contornar isso.


A definição oficial

De "The Basics" na linguagem de programação Swift :

O Swift também introduz tipos opcionais, que tratam da ausência de um valor. Os opcionais dizem "existe um valor e é igual a x" ou "não existe um valor". Os opcionais são semelhantes ao uso nulo com ponteiros no Objective-C, mas funcionam para qualquer tipo, não apenas para classes. Os opcionais são mais seguros e mais expressivos do que os ponteiros nulos no Objective-C e estão no centro de muitos dos recursos mais poderosos do Swift.

Os opcionais são um exemplo do fato de que Swift é um idioma seguro para o tipo. Swift ajuda você a ter clareza sobre os tipos de valores com os quais seu código pode trabalhar. Se parte do seu código espera uma String, o tipo safety impede que você transmita um Int por engano. Isso permite capturar e corrigir erros o mais cedo possível no processo de desenvolvimento.


Para terminar, aqui está um poema de 1899 sobre opcionais:

Ontem, na escada
, conheci um homem que não estava lá.
Ele não estava lá hoje novamente
. Desejo, desejo que ele fosse embora.

Antigonish


Mais recursos:


5
@KaanDedeoglu Infelizmente, Steve é ​​muito opcional. Ele estava aqui e agora não está.
Nevan king

19
if myStringnão compila mais. Você precisa if myString != nil. Veja a documentação .
Pang

5
melhor e mais clara explicação para? e! uso no Swift que encontrei na web. obrigado
mindbomb

2
mateo explica detalhadamente os opcionais, alcançando em profundidade e exemplos fáceis.
Iluvatar_GR 11/12

4
Obrigado por esta explicação, é muito mais claro que a documentação da Apple.
yesthisisjoe

16

Vamos dar o exemplo de um NSError, se não houver um erro sendo retornado, você deseja torná-lo opcional para retornar Nil. Não faz sentido atribuir um valor a ele se não houver um erro.

var error: NSError? = nil

Isso também permite que você tenha um valor padrão. Assim, você pode definir um método como um valor padrão se a função não receber nada

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}

A frase "Se for nula, o resultado de qualquer expressão com ela também é nula" está simplesmente errada. func isNil<T>(t: T?) -> Bool { return t == nil }retornará truemesmo se houver um valor opcional que esteja nilna expressão
return true

Exemplo de código incrivelmente ruim. Você não conseguia pensar em algo melhor? Por que não simplesmente return x == 5? O que há de tão especial em 5?
Atomosk

Não, há 2 anos eu não conseguia pensar em algo melhor. Hoje sim, mas isso esclarece? sim. Obrigado pela contribuição @Atomosk, é realmente útil.
John Riselvato

12

Você não pode ter uma variável que aponte para o nilSwift - não há ponteiros nem ponteiros nulos. Mas em uma API, você geralmente deseja indicar um tipo específico de valor ou falta de valor - por exemplo, minha janela tem um delegado e, se sim, quem é? Os opcionais são a maneira segura e de memória do Swift para fazer isso.


11

Fiz uma resposta curta, que resume a maioria dos itens acima, para limpar a incerteza que estava na minha cabeça como iniciante:

Ao contrário do Objective-C, nenhuma variável pode conter nulo no Swift; portanto, o tipo de variável Opcional foi adicionado (variáveis ​​com o sufixo "?"):

    var aString = nil //error

A grande diferença é que as variáveis ​​opcionais não armazenam valores diretamente (como as variáveis ​​normais de Obj-C) contêm dois estados : " has a value " ou " has nil ":

    var aString: String? = "Hello, World!"
    aString = nil //correct, now it contains the state "has nil"

Sendo assim, você pode verificar essas variáveis ​​em diferentes situações:

if let myString = aString? {
     println(myString)
}
else { 
     println("It's nil") // this will print in our case
}

Usando o "!" como sufixo, você também pode acessar os valores contidos neles, apenas se existirem . (ou seja, não é nulo ):

let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!

println(anotherString) //it will print "Hello, World!"

É por isso que você precisa usar "?" e "!" e não usar todos eles por padrão. (este foi o meu maior espanto)

Também concordo com a resposta acima: O tipo opcional não pode ser usado como booleano .


7

No objetivo C, variáveis ​​sem valor eram iguais a 'nil' (também era possível usar valores 'nil' iguais a 0 e false); portanto, era possível usar variáveis ​​em declarações condicionais (variáveis ​​com valores iguais a 'TRUE 'e aqueles sem valores foram iguais a' FALSE ').

Swift fornece segurança de tipo, fornecendo 'valor opcional'. ou seja, evita erros formados de atribuir variáveis ​​de tipos diferentes.

Portanto, no Swift, apenas booleanos podem ser fornecidos em instruções condicionais.

var hw = "Hello World"

Aqui, mesmo que 'hw' seja uma string, ela não pode ser usada em uma instrução if como no objetivo C.

//This is an error

if hw

 {..}

Para isso, ele precisa ser criado como,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}

5

O valor opcional permite mostrar a ausência de valor. Um pouco como NULL no SQL ou NSNull no Objective-C. Eu acho que isso será uma melhoria, pois você pode usar isso mesmo para tipos "primitivos".

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

Trecho de: Apple Inc. “A linguagem de programação Swift”. iBooks. https://itun.es/gb/jEUH0.l


6
nilé apenas açúcar sintático para a constante enum OptionalValue<T>.None(onde Té o tipo apropriado para o contexto em que você está usando nil). ?é um atalho para OptionalValue<T>.Some(T).
Rickster

4

Um opcional significa que Swift não tem certeza absoluta se o valor corresponde ao tipo: por exemplo, Int? significa que Swift não tem muita certeza se o número é um Int.

Para removê-lo, existem três métodos que você pode empregar.

1) Se você tem certeza absoluta do tipo, pode usar um ponto de exclamação para forçá-lo a desembrulhá-lo, assim:

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

Se você forçar a desembrulhar um opcional e for igual a zero, poderá encontrar este erro de falha:

insira a descrição da imagem aqui

Isso não é necessariamente seguro, então, aqui está um método que pode evitar falhas caso você não tenha certeza do tipo e valor:

Os métodos 2 e três protegem contra esse problema.

2) O opcional implicitamente desembrulhado

 if let unwrappedAge = age {

 // continue in here

 }

Observe que o tipo desembrulhado agora é Int , em vez de Int? .

3) A declaração de guarda

 guard let unwrappedAge = age else { 
   // continue in here
 }

A partir daqui, você pode prosseguir e usar a variável desembrulhada. Certifique-se de forçar a desembrulhar (com um!), Se tiver certeza do tipo da variável.

Boa sorte com seu projeto!


1

Quando comecei a aprender Swift, era muito difícil perceber o porquê opcional .

Vamos pensar dessa maneira. Vamos considerar uma classe Personque possui duas propriedades namee company.

class Person: NSObject {

    var name : String //Person must have a value so its no marked as optional
    var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible

    init(name:String,company:String?) {

        self.name = name
        self.companyName = company

    }
}

Agora vamos criar alguns objetos de Person

var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil

Mas não podemos passar Nilparaname

var personWithNoName:Person = Person.init(name: nil, company: nil)

Agora vamos falar sobre por que usamos optional?. Vamos considerar uma situação em que queremos adicionar o Incnome da empresa como appleserá apple Inc. Precisamos acrescentar o Incnome da empresa e imprimir.

print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.

Agora vamos estudar por que o opcional é implementado.

if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

Vamos substituir bobportom

if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

E parabéns! nós lidamos adequadamente comoptional?

Portanto, os pontos de realização são

  1. Marcaremos uma variável como opcional se for possível nil
  2. Se quisermos usar essa variável em algum lugar no compilador de código, você será lembrado de que precisamos verificar se temos uma negociação adequada com essa variável, se ela contiver nil.

Obrigado ... Happy Coding


0

Vamos experimentar com o código abaixo do Playground . Espero ter uma ideia clara do que é opcional e o motivo de usá-lo.

var sampleString: String? ///Optional, Possible to be nil

sampleString = nil ////perfactly valid as its optional

sampleString = "some value"  //Will hold the value

if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.

    print(value+value)  ////Sample String merged into Two
}

sampleString = nil // value is nil and the

if let value = sampleString{

    print(value + value)  ///Will Not execute and safe for nil checking
}

//   print(sampleString! + sampleString!)  //this line Will crash as + operator can not add nil

0

Em https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :

O encadeamento opcional é um processo para consultar e chamar propriedades, métodos e subscritos em um opcional que atualmente pode ser nulo. Se o opcional contiver um valor, a propriedade, método ou chamada subscrita será bem-sucedida; se o opcional for nulo, a propriedade, método ou chamada subscrita retornará nulo. Várias consultas podem ser encadeadas e a cadeia inteira falha normalmente se qualquer link da cadeia for nulo.

Para entender mais, leia o link acima.


0

Bem...

? (Opcional) indica que sua variável pode conter um valor nulo enquanto ! (desempacotador) indica que sua variável deve ter uma memória (ou valor) quando é usada (tentou obter um valor dela) em tempo de execução.

A principal diferença é que o encadeamento opcional falha normalmente quando o opcional é nulo, enquanto o desembrulhamento forçado aciona um erro de tempo de execução quando o opcional é nulo.

Para refletir o fato de que o encadeamento opcional pode ser chamado em um valor nulo, o resultado de uma chamada de encadeamento opcional é sempre um valor opcional, mesmo que a propriedade, o método ou o subscrito que você está consultando retorne um valor não opcional. Você pode usar esse valor de retorno opcional para verificar se a chamada de encadeamento opcional foi bem-sucedida (a opção retornada contém um valor) ou não teve êxito devido a um valor nulo na cadeia (o valor opcional retornado é nulo).

Especificamente, o resultado de uma chamada de encadeamento opcional é do mesmo tipo que o valor de retorno esperado, mas encapsulado em um opcional. Uma propriedade que normalmente retorna um Int retornará um Int? quando acessado através de encadeamento opcional.

var defaultNil : Int?  // declared variable with default nil value
println(defaultNil) >> nil  

var canBeNil : Int? = 4
println(canBeNil) >> optional(4)

canBeNil = nil
println(canBeNil) >> nil

println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper

var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4

var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error

Aqui está o tutorial básico em detalhes, pelo Apple Developer Committee: Encadeamento opcional



-1

Aqui está uma declaração opcional equivalente no Swift:

var middleName: String?

Esta declaração cria uma variável chamada middleName do tipo String. O ponto de interrogação (?) Após o tipo de variável String indica que a variável middleName pode conter um valor que pode ser String ou nulo. Qualquer pessoa que observe esse código imediatamente sabe que middleName pode ser nulo. É auto-documentado!

Se você não especificar um valor inicial para uma constante ou variável opcional (como mostrado acima), o valor será automaticamente definido como nulo para você. Se preferir, você pode definir explicitamente o valor inicial como nulo:

var middleName: String? = nil

Para obter mais detalhes, leia o link opcional abaixo.

http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values


use isso, var middleName: String! = ""
Gaurav
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.