Saat memanggil fungsi yang dideklarasikan dengan throws
di Swift, Anda harus membuat anotasi situs panggilan fungsi dengan try
atau try!
. Misalnya, diberi fungsi melempar:
func willOnlyThrowIfTrue(value: Bool) throws {
if value { throw someError }
}
fungsi ini bisa disebut seperti:
func foo(value: Bool) throws {
try willOnlyThrowIfTrue(value)
}
Di sini kita membubuhi keterangan panggilan try
, yang memanggil pembaca bahwa fungsi ini dapat menimbulkan pengecualian, dan setiap baris kode berikut mungkin tidak dieksekusi. Kita juga harus membubuhi keterangan fungsi ini throws
, karena fungsi ini bisa melempar pengecualian (yaitu, ketika willOnlyThrowIfTrue()
melempar, maka foo
akan secara otomatis menggabungkan kembali pengecualian ke atas.
Jika Anda ingin memanggil fungsi yang dinyatakan sebagai kemungkinan melempar, tetapi yang Anda tahu tidak akan melempar dalam kasus Anda karena Anda memberikan input yang benar, Anda dapat menggunakannya try!
.
func bar() {
try! willOnlyThrowIfTrue(false)
}
Dengan cara ini, ketika Anda menjamin bahwa kode tidak akan dibuang, Anda tidak perlu memasukkan kode boilerplate tambahan untuk menonaktifkan propagasi pengecualian.
try!
diberlakukan pada saat runtime: jika Anda menggunakan try!
dan fungsi tersebut akhirnya membuang, maka eksekusi program Anda akan diakhiri dengan kesalahan runtime.
Sebagian besar pengecualian menangani kode harus terlihat seperti di atas: Anda cukup menyebarkan pengecualian ke atas ketika mereka terjadi, atau Anda mengatur kondisi sehingga pengecualian yang mungkin dikesampingkan. Setiap pembersihan sumber daya lain dalam kode Anda harus terjadi melalui penghancuran objek (yaitu deinit()
), atau kadang-kadang melalui defer
kode ed.
func baz(value: Bool) throws {
var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt")
var data = NSData(contentsOfFile:filePath)
try willOnlyThrowIfTrue(value)
// data and filePath automatically cleaned up, even when an exception occurs.
}
Jika karena alasan apa pun Anda memiliki kode pembersihan yang perlu dijalankan tetapi tidak deinit()
berfungsi, Anda dapat menggunakannya defer
.
func qux(value: Bool) throws {
defer {
print("this code runs when the function exits, even when it exits by an exception")
}
try willOnlyThrowIfTrue(value)
}
Sebagian besar kode yang berhubungan dengan pengecualian hanya membuat mereka menyebar ke atas ke penelepon, melakukan pembersihan di jalan melalui deinit()
atau defer
. Ini karena sebagian besar kode tidak tahu apa yang harus dilakukan dengan kesalahan; ia tahu apa yang salah, tetapi tidak memiliki informasi yang cukup tentang apa yang beberapa kode tingkat tinggi coba lakukan untuk mengetahui apa yang harus dilakukan tentang kesalahan. Itu tidak tahu apakah menyajikan dialog kepada pengguna sesuai, atau apakah itu harus mencoba lagi, atau jika sesuatu yang lain sesuai.
Namun, kode tingkat yang lebih tinggi harus tahu persis apa yang harus dilakukan jika terjadi kesalahan. Jadi pengecualian memungkinkan kesalahan spesifik muncul dari tempat awalnya terjadi ke tempat penanganannya.
Menangani pengecualian dilakukan melalui catch
pernyataan.
func quux(value: Bool) {
do {
try willOnlyThrowIfTrue(value)
} catch {
// handle error
}
}
Anda dapat memiliki beberapa pernyataan penangkapan, masing-masing menangkap jenis pengecualian yang berbeda.
do {
try someFunctionThatThowsDifferentExceptions()
} catch MyErrorType.errorA {
// handle errorA
} catch MyErrorType.errorB {
// handle errorB
} catch {
// handle other errors
}
Untuk detail lebih lanjut tentang praktik terbaik dengan pengecualian, lihat http://exceptionsafecode.com/ . Ini khusus ditujukan untuk C ++, tetapi setelah memeriksa model pengecualian Swift, saya percaya dasar-dasar berlaku untuk Swift juga.
Untuk detail tentang sintaks Swift dan model penanganan kesalahan, lihat buku Swift Programming Language (Swift 2 Prerelease) .