спробуйте, спробуйте! & спробувати? в чому різниця, і коли використовувати кожен?


172

У Swift 2.0 Apple представила новий спосіб вирішення помилок (do-try-catch). А кілька днів тому в Beta 6 було введено ще новіше ключове слово ( try?). Також знав, що можу використовувати try!. Яка різниця між трьома ключовими словами та коли їх використовувати?

Відповіді:


316

Оновлено для Swift 5.1

Припустимо наступну функцію метання:

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)
  }
}

спробуйте

У вас є два варіанти, коли ви намагаєтесь викликати функцію, яка може кинути.

Ви можете взяти на себе відповідальність за обробку помилок , оточуючи свій дзвінок у межах блоку, що робить улов:

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)
}

Або просто спробуйте викликати функцію та передати помилку наступному абоненту в ланцюзі викликів:

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

спробуйте!

Що відбувається, коли ви намагаєтесь отримати доступ до неявно розгорнутого факультативу з нулем всередині нього? Так, правда, додаток буде РОЗКРИТИ! Те саме стосується і спробу! він в основному ігнорує ланцюжок помилок і оголошує ситуацію "зроби чи помри". Якщо викликана функція не кинула жодних помилок, все буде добре. Але якщо вона не вдалася і виникла помилка, ваша програма просто вийде з ладу .

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

спробувати?

Нове ключове слово, яке було введено в Xcode 7 beta 6. Він повертає необов’язкове, що розгортає успішні значення та виявляє помилку, повертаючи нуль.

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

Або ми можемо використовувати охорону:

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

Останнє зауваження тут, використовуючи try?зауваження, що ви відкидаєте помилку, яка сталася, оскільки вона переведена на нуль. Використовувати спробу? коли ви більше зосереджуєтесь на успіхах і невдачах, а не на тому, чому все вийшло з ладу.

Використання оператора злиття ??

Ви можете використовувати оператор злиття ?? з спробу? надати значення за замовчуванням у разі відмови:

let result = (try? doSomething()) ?? "Default Value"
print(result) // Default Value

Ваш другий зразок коду ( let result = try doSomething() // Not within a do-catch block) повинен викликатись із методу, який оголошується як throws, правда? Отже, якщо doSomething()не вдається, то чи зовнішній метод теж (по черзі)?
Nicolas Miari

Стара тема та все, але я виявив, що сьогодні (Swift 4, Xcode 9.1) спробуйте? не автоматично розгортає результат. Це просто залишає це як звичайний необов'язковий варіант, який ви зможете розгортати вручну. Не впевнений, чи змінилося це після Swift 2/3, але це відповідає документам: developer.apple.com/library/content/documentation/Swift/… (див. Перетворення помилок у необов’язкові значення ). Відмінне пояснення спробувати btw.
the_dude_abides

1
в швидкому 4, спробувати? не знімає жодних викликів перекидання функцій у виразах "спробувати" у моєму проекті.
aznelite89

7
Ви також можете використовувати try?з ??таким чином, це дозволить вам визначити значення за замовчуванням в одному рядку:let something:String = (try? whateverIfItThrows()) ?? "Your default value here"
itMaxence
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.