coba coba! & coba? apa bedanya, dan kapan menggunakannya?

172

Di Swift 2.0 , Apple memperkenalkan cara baru untuk menangani kesalahan (do-try-catch). Dan beberapa hari yang lalu di Beta 6 kata kunci yang lebih baru diperkenalkan ( try?). Juga, tahu bahwa saya bisa menggunakan try!. Apa perbedaan antara 3 kata kunci, dan kapan harus menggunakannya?

Gus Dur
sumber

Jawaban:

316

Diperbarui untuk Swift 5.1

Asumsikan fungsi melempar berikut:

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

mencoba

Anda memiliki 2 opsi ketika Anda mencoba memanggil fungsi yang mungkin melempar.

Anda dapat mengambil tanggung jawab menangani kesalahan dengan mengelilingi panggilan Anda di dalam blok do-catch:

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

Atau coba panggil fungsi tersebut, dan teruskan kesalahannya ke penelepon berikutnya dalam rantai panggilan:

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

mencoba!

Apa yang terjadi ketika Anda mencoba mengakses opsi yang secara implisit tidak terbuka dengan nol di dalamnya? Ya benar, aplikasinya akan CRASH! Sama halnya dengan mencoba! pada dasarnya mengabaikan rantai kesalahan, dan menyatakan situasi "lakukan atau mati". Jika fungsi yang dipanggil tidak membuang kesalahan, semuanya berjalan dengan baik. Tetapi jika itu gagal dan membuat kesalahan, aplikasi Anda hanya akan crash .

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

mencoba?

Kata kunci baru yang diperkenalkan dalam Xcode 7 beta 6. Ini mengembalikan opsional yang membuka nilai sukses, dan menangkap kesalahan dengan mengembalikan nihil.

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

Atau kita bisa menggunakan penjaga:

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

Satu catatan terakhir di sini, dengan menggunakan try?catatan bahwa Anda membuang kesalahan yang terjadi, karena diterjemahkan ke nol. Gunakan coba? ketika Anda lebih fokus pada keberhasilan dan kegagalan, bukan pada mengapa semuanya gagal.

Menggunakan Operator Penggabungan ??

Anda dapat menggunakan operator penggabungan ?? dengan coba? untuk memberikan nilai default jika gagal:

let result = (try? doSomething()) ?? "Default Value"
print(result) // Default Value
Gus Dur
sumber
Sampel kode kedua Anda ( let result = try doSomething() // Not within a do-catch block) harus dipanggil dari dalam metode yang dinyatakan throws, kan? Jadi, jika doSomething()gagal, apakah metode luar juga (pada gilirannya)?
Nicolas Miari
Utas lama dan semuanya tetapi saya menemukan bahwa hari ini (Swift 4, Xcode 9.1) coba? tidak membuka secara otomatis hasilnya. Itu hanya menjadikannya sebagai pilihan normal bagi Anda untuk membuka secara manual. Tidak yakin apakah ini berubah sejak Swift 2/3 tetapi sesuai dengan dokumen: developer.apple.com/library/content/documentation/Swift/… (lihat Konversi Kesalahan ke Nilai Opsional ). Penjelasan hebat tentang coba btw.
the_dude_abides
1
di swift 4, coba? tidak menghapus tidak ada panggilan ke fungsi melempar terjadi dalam ekspresi 'coba' di proyek saya.
aznelite89
7
Anda juga dapat menggunakan try?dengan ??itu sehingga Anda dapat menentukan nilai default dalam satu baris:let something:String = (try? whateverIfItThrows()) ?? "Your default value here"
itMaxence