Error handler
แม้ว่าโดยทั่วไปฟังก์ชั่นใน Swift หรือจากไลบารีจะไม่ค่อยมี Error เกิดขึ้น แต่ในบางครั้ง บางฟังก์ชั่นก็มีการส่ง Error ออกมา ซึ่งเราสามารถดูได้จาก signature ของฟังก์ชั่นนั้น ฟังก์ชั่นที่สามารถส่ง Error ออกมาได้ จะมี keyword throws
หน้าตาประมาณนี้
func canThrowErrors() throws -> String
เมื่อฟังก์ชั่นสามารถที่จะ throw error ออกมาได้ ฝั่งที่เรียกใช้งานฟังก์ชั่นจึงต้องเขียนรองรับการส่ง error ออกมาด้วย do catch
โดยจะต้องมี try
อยู่ที่หน้าฟังก์ชั่นที่ throw error ได้
do {
let user = try decode()
print(user.name)
} catch {
print(error)
}
จากตัวอย่างโค้ด ฟังก์ชั่น decode สามารถ throw error ออกมา จึงต้องครอบด้วย do catch
และใส่ try
ขณะเรียก decode
ในบล๊อก catch
จะได้ตัวแปร error
มาโดยอัตโนมัติ
ในกรณีที่ต้องการ handle แต่ละ Error แยกกัน สามารถ catch แยกกันได้
enum VendingMachineError: Error {
case invalidSelection
case outOfStock
case insufficientFunds(coinsNeeded: Int)
}
func buyFavoriteSnack() throws {
throw VendingMachineError.insufficientFunds(coinsNeeded: 9)
}
do {
try buyFavoriteSnack()
} catch VendingMachineError.invalidSelection {
print("invalid selection")
} catch VendingMachineError.insufficientFunds(let coinsNeeded) {
print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")
} catch {
print(error)
}
ในบางครั้งเราอาจจะเห็นโค้ดแบบนี้
let user = try? decode()
คือไม่ใส่ do catch
ในกรณีนี้ user
จะกลายเป็น optional ไปด้วย และถ้าฟังก์ชั่น decode throw error ออกมา user
จะเป็น nil
ในทางกลับกัน try!
ก็สามารถใช้งานได้เช่นกัน ถ้าไม่ error ผลลัพธ์ที่ได้จะไม่ใช่ optional แต่ถ้ามี error แอปเราก็จะ crash
The guard Statement
ในบางครั้งการทำ optional binding และการตรวจสอบเงื่อนไขจะทำให้เรามี nested if
ซ้อนเข้าไปเรื่อย ทำให้เราอ่านยาก
func isValid(text: String?) -> Bool {
if let text = text {
if text.count != 5 {
return false
}
if !text.hasPrefix("W") {
return false
}
print(text)
return true
}
return false
}
swift จึงมี guard
ให้เราใช้ ซึ่งจะทำหน้าที่คล้าย ๆ กับตรงข้ามกับ if
แต่ในบล๊อก guard จะต้อง return ทุกครั้งที่ทำเสร็จ
func isValid(text: String?) -> Bool {
guard let text = text, text.count == 5, text.hasPrefix("W") else {
return false
}
print(text)
return true
}
จากตัวอย่าง guard จะทำ optional binding และ ตรวจสอบเงื่อนไข ถ้าทั้งหมดเป็นจริง บล๊อก guard จะไม่ทำงานและรันลงมาต่อที่บรรทัด 5 ตัวแปร text จะไม่ใช่ optional แล้ว
แต่ถ้าไม่สามารถ unwrap text ได้ หรือเงื่อนไขไม่เป็นความจริง บล๊อก guard จะทำงานและ return false ออกไป
Last updated