tente tente! & experimentar? qual é a diferença e quando usar cada uma?

172

No Swift 2.0 , a Apple introduziu uma nova maneira de lidar com erros (do-try-catch). E alguns dias atrás, no Beta 6, uma palavra-chave ainda mais recente foi introduzida ( try?). Além disso, sabia que eu posso usar try!. Qual é a diferença entre as três palavras-chave e quando usar cada uma?

Abdurrahman
fonte

Respostas:

316

Atualizado para o Swift 5.1

Assuma a seguinte função de arremesso:

enum ThrowableError: Error {

    case badError(howBad: Int)
}

func doSomething(everythingIsFine: Bool = false) throws -> String {

  if everythingIsFine {
      return "Everything is ok"
  } else {
      throw ThrowableError.badError(howBad: 4)
  }
}

experimentar

Você tem duas opções ao tentar chamar uma função que pode ser lançada.

Você pode assumir a responsabilidade de lidar com erros cercando sua chamada dentro de um bloco de captura e captura:

do {
    let result = try doSomething()
}
catch ThrowableError.badError(let howBad) {
    // Here you know about the error
    // Feel free to handle or to re-throw

    // 1. Handle
    print("Bad Error (How Bad Level: \(howBad)")

    // 2. Re-throw
    throw ThrowableError.badError(howBad: howBad)
}

Ou apenas tente chamar a função e repasse o erro para o próximo chamador na cadeia de chamadas:

func doSomeOtherThing() throws -> Void {    
    // Not within a do-catch block.
    // Any errors will be re-thrown to callers.
    let result = try doSomething()
}

experimentar!

O que acontece quando você tenta acessar um opcional implicitamente desembrulhado com um nulo dentro dele? Sim, é verdade, o aplicativo vai bater! O mesmo acontece com a tentativa! basicamente ignora a cadeia de erros e declara uma situação de "faça ou morra". Se a função chamada não gerou nenhum erro, tudo vai bem. Mas se ele falhar e gerar um erro, seu aplicativo simplesmente trava .

let result = try! doSomething() // if an error was thrown, CRASH!

experimentar?

Uma nova palavra-chave que foi introduzida no Xcode 7 beta 6. Ele retorna um opcional que quebra os valores bem-sucedidos e captura o erro retornando zero.

if let result = try? doSomething() {
    // doSomething succeeded, and result is unwrapped.
} else {
    // Ouch, doSomething() threw an error.
}

Ou podemos usar guarda:

guard let result = try? doSomething() else {
    // Ouch, doSomething() threw an error.
}
// doSomething succeeded, and result is unwrapped.

Uma nota final aqui, usando a try?nota de que você está descartando o erro que ocorreu, pois é traduzido para zero. Use try? quando você está focando mais em sucessos e fracassos, não em por que as coisas falharam.

Usando Operador Coalescente?

Você pode usar o operador coalescente? com tentar? para fornecer um valor padrão em caso de falha:

let result = (try? doSomething()) ?? "Default Value"
print(result) // Default Value
Abdurrahman
fonte
Seu segundo exemplo de código ( let result = try doSomething() // Not within a do-catch block) deve ser chamado de dentro de um método declarado como throws, certo? Então, se doSomething()falhar, o método externo também (por sua vez)?
Nicolas Miari
Tópico antigo e tudo, mas eu achei que hoje (Swift 4, Xcode 9.1) tente? não desembrulha automaticamente o resultado. Apenas o deixa como um opcional normal para você desembrulhar manualmente. Não tenho certeza se isso mudou desde o Swift 2/3, mas é conforme os documentos: developer.apple.com/library/content/documentation/Swift/… (consulte Convertendo erros em valores opcionais ). Ótima explicação da tentativa btw.
the_dude_abides
1
no swift 4, tente? não remove as chamadas no para funções de lançamento ocorrem dentro das expressões 'try' no meu projeto.
aznelite89
7
Você também pode usar try?com ??para que ele iria deixá-lo definir um valor padrão em uma linha:let something:String = (try? whateverIfItThrows()) ?? "Your default value here"
itMaxence