Do-Catch: คืออะไร โครงสร้างและการจัดการข้อผิดพลาดใน Swift

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-05-26 เวลาอ่าน: 8 นาที

Do-Catch คือโครงสร้างภาษา Swift สำหรับการจัดการข้อผิดพลาด ซึ่งดักจับข้อยกเว้นที่ถูกโยนผ่าน throw และดำเนินการบล็อกโค้ดที่เกี่ยวข้อง แตกต่างจาก try-catch แบบดั้งเดิมในภาษาอื่น Swift ต้องการให้ฟังก์ชันที่อาจโยนข้อผิดพลาดถูกระบุอย่างชัดเจนด้วยตัวปรับ throws จากข้อมูลของ Swift.org, 2026 Do-Catch เป็นกลไกหลักในการจัดการข้อผิดพลาดใน Swift ที่รับประกันความปลอดภัยระดับชนิดข้อมูล

หัวข้อสำคัญ

  • Do-Catch คือโครงสร้าง Swift ที่ดักจับข้อผิดพลาดจากบล็อกที่มี try และ throw
  • throws คือตัวบ่งชี้ฟังก์ชันที่บอกว่าฟังก์ชันนั้นอาจโยนข้อผิดพลาด
  • try คือคำหลักสำหรับเรียกใช้ฟังก์ชัน throwing ภายใน do-บล็อก
  • catch คือบล็อกจัดการข้อผิดพลาดที่สามารถจับคู่ตามชนิดได้
  • try? และ try! คือรูปแบบอื่นที่แปลงข้อผิดพลาดเป็น nil หรือทำให้เกิด crash

Do-Catch คืออะไร?

Do-Catch คือโครงสร้างใน Swift ที่ประกอบด้วยบล็อก do ซึ่งภายในมีการดำเนินการโค้ดที่อาจโยนข้อผิดพลาด และบล็อก catch หนึ่งบล็อกหรือมากกว่าที่จัดการข้อผิดพลาดนั้น บล็อก do ประกอบด้วยการเรียกใช้ฟังก์ชัน throwing ที่มีคำว่า try กำกับ และบล็อก catch จะจับคู่ข้อผิดพลาดตามชนิด

Swift ใช้โมเดล การจัดการข้อผิดพลาดแบบมีโครงสร้าง ที่แตกต่างจากข้อยกเว้นใน Objective-C ที่นี่ข้อผิดพลาดไม่ใช่ exception ที่มีการคลายสแต็ก แต่เป็นค่าที่สอดคล้องกับโปรโตคอล Error การโยนข้อผิดพลาดผ่าน throw จะส่งผ่านการควบคุมไปยังบล็อก catch ที่ใกล้ที่สุดโดยไม่มีค่าใช้จ่ายในการคลายสแต็ก

คุณสมบัติสำคัญของ Swift คือ ความชัดเจนในการจัดการ คอมไพเลอร์ไม่อนุญาตให้เรียกใช้ฟังก์ชัน throwing โดยไม่มี try, do-catch หรือกลไกอื่น (try?, try!) ซึ่งช่วยขจัดสถานการณ์ที่ข้อผิดพลาดถูกมองข้าม

โมเดลข้อผิดพลาดใน Swift: โปรโตคอล Error และฟังก์ชัน throwing

พื้นฐานของการจัดการข้อผิดพลาดใน Swift คือโปรโตคอล Error ชนิดใดก็ตามที่สอดคล้องกับโปรโตคอลนี้สามารถถูกโยนผ่าน throw ได้ โดยทั่วไปข้อผิดพลาดจะถูกกำหนดเป็น enum ที่ยืนยัน Error

โปรโตคอล Error

Error คือโปรโตคอลว่าง (ตัวบ่งชี้) ไม่ต้องการการดำเนินการเมธอด เพียงแค่ยืนยันความสอดคล้องเท่านั้น คอมไพเลอร์ Swift ใช้ Error สำหรับการตรวจสอบแบบสแตติก: ฟังก์ชันที่มี throws สามารถโยนเฉพาะค่าที่สอดคล้องกับ Error

ฟังก์ชัน Throwing

ฟังก์ชันที่มี throws ต้องถูกเรียกด้วย try หากภายในฟังก์ชันดังกล่าวมี throw เกิดขึ้น การควบคุมจะถูกส่งไปยัง do-catch ที่เรียกใช้ หากข้อผิดพลาดไม่ได้รับการจัดการในห่วงโซ่การเรียกใด ๆ ข้อผิดพลาดนั้นจะถูกส่งขึ้นไปยังระดับที่สูงขึ้น

swift
enum FileError: Error {
    case notFound
    case permissionDenied
    case corrupted(String)
}

func readFile(path: String) throws -> String {
    guard FileManager.default.fileExists(atPath: path) else {
        throw FileError.notFound
    }
    return try String(contentsOfFile: path)
}

การส่งต่อข้อผิดพลาด rethrows

rethrows คือตัวปรับสำหรับฟังก์ชันที่รับ throwing-closure เป็นพารามิเตอร์ หาก closure ที่ส่งมาไม่โยนข้อผิดพลาด การเรียกใช้ฟังก์ชัน rethrows สามารถทำได้โดยไม่ต้องมี try ซึ่งช่วยให้เขียนฟังก์ชันลำดับสูงทั่วไปที่เข้ากันได้กับทั้ง throwing และ non-throwing closures

ไวยากรณ์ Do-Catch: บล็อก catch หลายบล็อก

Swift รองรับบล็อก catch หลายบล็อก พร้อมการจับคู่ตามชนิดข้อผิดพลาด คล้ายกับ when ใน Kotlin หรือ switch ตามชนิด: catch ที่ตรงกันตัวแรกจะถูกดำเนินการ ส่วนที่เหลือจะถูกข้ามไป

การจับคู่ตามชนิด

แต่ละบล็อก catch สามารถมีรูปแบบการจับคู่กับชนิดข้อผิดพลาดที่เฉพาะเจาะจงได้ Swift จะตรวจสอบบล็อกตามลำดับ ดังนั้นชนิดที่เฉพาะเจาะจงกว่าควรอยู่ก่อนชนิดทั่วไป หากไม่มีรูปแบบใดตรงกัน บล็อก catch ที่ไม่มีรูปแบบจะถูกดำเนินการ

การจัดการหลายชนิด

ความปลอดภัยของชนิดข้อมูล ของ Do-Catch ช่วยให้จัดการข้อผิดพลาดแต่ละรายการแยกกัน หรือรวมหลายชนิดในบล็อกเดียวผ่านเครื่องหมายจุลภาคในการจับคู่รูปแบบ ซึ่งช่วยลดลูกโซ่ if-else ที่เทอะทะซึ่งเป็นลักษณะเฉพาะของ Objective-C ที่การวิเคราะห์ข้อผิดพลาดดำเนินการผ่านรหัสส่งกลับหรือ NSError พร้อมการตรวจสอบ domain และ code

Swift ยังรองรับ catch where ซึ่งเป็นการจับคู่กับเงื่อนไขเพิ่มเติม ตัวอย่างเช่น สามารถกรองข้อผิดพลาดตามรหัสหรือข้อความเฉพาะ: catch URLError where error.code == .notConnectedToInternet ซึ่งช่วยลดจำนวนบล็อก catch ในขณะที่คงความแม่นยำในการจัดการ

สำหรับการดีบักฟังก์ชัน throwing Swift มี ความแตกต่างระหว่างข้อผิดพลาดและข้อยกเว้น ข้อผิดพลาดของ Swift คือค่าส่งกลับที่ไม่ต้องคลายสแต็ก ข้อยกเว้นของ Objective-C (@try/@catch) ทำงานที่ระดับ runtime และใช้สำหรับข้อผิดพลาดร้ายแรงเท่านั้น Do-Catch จัดการกับข้อผิดพลาด ไม่ใช่ข้อยกเว้น ซึ่งทำให้คาดเดาได้และมีประสิทธิภาพ

ในการพัฒนาไลบรารีและ SDK สิ่งสำคัญคือต้องจำไว้ว่าฟังก์ชัน throwing เป็นส่วนหนึ่งของ สัญญาสาธารณะ ชนิดข้อผิดพลาดไม่ได้ระบุในลายเซ็น ดังนั้นควรบันทึกว่าฟังก์ชันสามารถโยนข้อผิดพลาดใดได้บ้างในความคิดเห็นหรือผ่าน enum คล้าย Result ซึ่งช่วยให้ผู้ใช้ API เขียนบล็อก catch ที่ถูกต้องโดยไม่ต้องดูการดำเนินการภายใน

ในบริบทของ การเขียนโปรแกรมแบบอะซิงโครนัส Do-Catch กับ async/await ช่วยแก้ปัญหา callback hell ก่อนหน้านี้ใน Swift การจัดการข้อผิดพลาดในโค้ดอะซิงโครนัสต้องใช้ closures ที่ซ้อนกันพร้อมการตรวจสอบ Error? ใน completion handler ด้วย async/await และ Do-Catch โค้ด throwing อะซิงโครนัสจะดูเหมือนโค้ดซิงโครนัส ซึ่งช่วยให้อ่านและบำรุงรักษาห่วงโซ่คำขอที่ซับซ้อนพร้อมการจัดการข้อผิดพลาดในแต่ละขั้นตอนได้ง่ายขึ้น

swift
do {
    let content = try readFile(path: "/data/config.json")
    process(content)
} catch FileError.notFound {
    createDefaultConfig()
} catch FileError.permissionDenied {
    requestAccess()
} catch FileError.corrupted(let detail) {
    logCorruption(detail)
} catch {
    print("ข้อผิดพลาดที่ไม่ทราบสาเหตุ: \(error)")
}

รูปแบบ Try: try, try?, try! และเมื่อใดควรใช้

Swift มีสามรูปแบบในการเรียกใช้ฟังก์ชัน throwing: try, try? และ try! แต่ละรูปแบบแก้ปัญหาเฉพาะและมีข้อจำกัดของตัวเอง

try — การเรียกมาตรฐาน

try ใช้ภายใน do-บล็อก และข้อผิดพลาดจะถูกจัดการใน catch นี่คือวิธีหลักในการเรียกใช้ฟังก์ชัน throwing คอมไพเลอร์ต้องการให้ try อยู่ในบริบทที่ข้อผิดพลาดสามารถถูกดักจับได้

try? — การแปลงเป็น Optional

try? แปลงผลลัพธ์ของฟังก์ชัน throwing เป็น Optional หากฟังก์ชันโยนข้อผิดพลาด try? จะส่งคืน nil มิฉะนั้นจะส่งคืน Optional พร้อมค่าที่สำเร็จ สะดวกสำหรับการเรียกที่สามารถละเว้นข้อผิดพลาดได้ แต่ต้องการตัวบ่งชี้ความสำเร็จ

try! — การดำเนินการบังคับ

try! จะระงับการจัดการข้อผิดพลาด หากฟังก์ชัน throwing โยนข้อผิดพลาด แอปพลิเคชันจะสิ้นสุดลงด้วย runtime error ใช้ try! เฉพาะเมื่อมั่นใจอย่างแน่นอนว่าข้อผิดพลาดเป็นไปไม่ได้ เช่น เมื่อโหลดทรัพยากรในตัว

swift
// try? — ละเว้นข้อผิดพลาด ได้ nil เมื่อเกิดข้อผิดพลาด
if let data = try? Data(contentsOf: url) {
    processData(data)
}

// try! — เฉพาะเมื่อมั่นใจว่าข้อผิดพลาดเป็นไปไม่ได้
let bundled = try! String(contentsOfFile: "Assets/default.txt")

// try — ตัวเลือกมาตรฐานใน do-catch
do {
    let result = try performNetworkRequest()
    updateUI(result)
} catch {
    showError(error)
}

Do-Catch ในการพัฒนา iOS: ตัวอย่างเชิงปฏิบัติ

Do-Catch ถูกใช้อย่างแพร่หลายในการพัฒนา iOS สำหรับการทำงานกับ API ของระบบ มาดูสถานการณ์ทั่วไป: การทำงานกับระบบไฟล์ Core Data และคำขอเครือข่าย

ระบบไฟล์

หลายเมธอดของ FileManager เป็น throwing Do-Catch ช่วยจัดการการไม่มีไฟล์ ทรัพยากรถูกใช้งาน หรือสิทธิ์ไม่เพียงพอได้อย่างถูกต้อง

คำขอเครือข่ายกับ Codable

การแยกวิเคราะห์ JSON ผ่าน JSONDecoder เป็นการดำเนินการแบบ throwing Do-Catch จะดักจับข้อผิดพลาดในการถอดรหัสและข้อผิดพลาดเครือข่ายแยกกัน โดยให้ข้อความข้อผิดพลาดที่แม่นยำแก่ผู้ใช้

swift
struct User: Codable {
    let id: Int
    let name: String
}

func fetchUser(id: Int) async throws -> User {
    let url = URL(string: "https://api.example.com/users/\(id)")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return try JSONDecoder().decode(User.self, from: data)
}

// การเรียกพร้อมการจัดการ
do {
    let user = try await fetchUser(id: 42)
    showUser(user)
} catch let error as URLError {
    showNetworkAlert(error)
} catch let error as DecodingError {
    showParseError(error)
} catch {
    showGenericError(error)
}

ข้อผิดพลาดทั่วไปเมื่อทำงานกับ Do-Catch

นักพัฒนา โดยเฉพาะผู้ที่ย้ายมาจากภาษาอื่น มักทำผิดพลาดลักษณะเฉพาะเมื่อใช้ Do-Catch มาดูข้อผิดพลาดที่พบบ่อยที่สุดกัน

  • ลืม try — การเรียกฟังก์ชัน throwing โดยไม่มี try จะทำให้เกิดข้อผิดพลาดในการคอมไพล์ Swift ไม่อนุญาตให้ละเว้นข้อผิดพลาดโดยปริยาย
  • catch ว่างเปล่า — บล็อก catch ที่ไม่มีการจัดการจะซ่อนข้อผิดพลาด ควรบันทึกหรือจัดการข้อผิดพลาดเสมอ แม้ว่าจะดูเหมือนเป็นไปไม่ได้
  • catch ไม่มีการจับคู่ — catch ทั่วไปเพียงบล็อกเดียวสำหรับข้อผิดพลาดทั้งหมดจะทำให้สูญเสียข้อดีของความปลอดภัยของชนิดข้อมูล ควรแยกการจัดการตามชนิดผ่านหลายบล็อก
  • การใช้ try! มากเกินไป — try! ในโค้ด production เป็นแหล่งของ crash ที่ไม่คาดคิด ใช้เฉพาะสำหรับทรัพยากรในตัวหรือการทดสอบเท่านั้น

คำถามที่พบบ่อย

Do-Catch ใน Swift แตกต่างจาก try-catch ในภาษาอื่นอย่างไร?

ใน Swift ข้อผิดพลาดคือค่าที่สอดคล้องกับโปรโตคอล Error ไม่ใช่ exception ที่มีการคลายสแต็ก ฟังก์ชัน Throwing ต้องถูกระบุอย่างชัดเจนด้วย throws และคอมไพเลอร์ต้องการ try เมื่อเรียกใช้ ซึ่งช่วยขจัดข้อผิดพลาดที่ไม่ได้รับการจัดการในขั้นตอนการคอมไพล์

สามารถใช้ Do-Catch กับ async/await ได้หรือไม่?

ได้ async ฟังก์ชันสามารถเป็น throws ได้เช่นกัน และ do-catch ทำงานร่วมกับมันได้ การเรียกใช้ฟังก์ชัน async throwing ต้องใช้ try await ภายใน do-บล็อก นี่คือวิธีมาตรฐานในการจัดการข้อผิดพลาดในโค้ดอะซิงโครนัสของ Swift

จะจัดการข้อผิดพลาดโดยไม่ใช้ do-catch ได้อย่างไร?

มีทางเลือกอื่น: try? แปลงข้อผิดพลาดเป็น nil, try! ทำให้เกิด crash เมื่อมีข้อผิดพลาด และ rethrows ช่วยส่งต่อข้อผิดพลาดจาก closure Do-catch ยังคงเป็นวิธีหลักในการจัดการอย่างชัดเจน

ฟังก์ชันเดียวสามารถโยนข้อผิดพลาดหลายชนิดได้หรือไม่?

Swift ไม่ได้กำหนดชนิดของข้อผิดพลาดที่โยนได้ — ฟังก์ชัน throwing ใด ๆ สามารถโยนชนิดใดก็ได้ที่สอดคล้องกับ Error ให้แยกการจัดการผ่านการจับคู่ใน catch ตามชนิดข้อผิดพลาดที่เฉพาะเจาะจง

ควรห่อหุ้มข้อผิดพลาดทั้งหมดเป็นชนิดกำหนดเองหรือไม่?

ใช่ นี่คือแนวปฏิบัติที่ดีที่สุด กำหนด AppError เป็น enum ที่ยืนยัน Error และแปลงข้อผิดพลาดของระบบเป็นข้อผิดพลาดของโดเมน ซึ่งจะรวมการจัดการและแยกระดับแอปพลิเคชันจากรายละเอียดของระบบ

สรุป

  • Do-Catch คือโครงสร้าง Swift สำหรับการจัดการข้อผิดพลาดที่มีการระบุ throws บนฟังก์ชันและ try เมื่อเรียกใช้
  • ข้อผิดพลาดของ Swift คือค่าที่สอดคล้องกับโปรโตคอล Error ไม่ใช่ข้อยกเว้นที่มีการคลายสแต็ก ซึ่งทำให้ไม่มีค่าใช้จ่ายเพิ่มเติมเมื่อไม่มีข้อผิดพลาด
  • หลาย catch ช่วยจัดการข้อผิดพลาดชนิดต่าง ๆ แยกกันด้วยการจับคู่รูปแบบที่คล้ายกับ switch
  • try? แปลงข้อผิดพลาดเป็น nil สำหรับสถานการณ์ง่าย ๆ try! คือการเรียกแบบบังคับที่เสี่ยงต่อการ crash ใช้เฉพาะสำหรับการดำเนินการที่สำเร็จแน่นอน
  • Do-Catch กับ async/await เป็นวิธีมาตรฐานในการจัดการข้อผิดพลาดในโค้ด Swift อะซิงโครนัสโดยใช้ try await
  • หลีกเลี่ยง catch ว่างเปล่า และการใช้ try! มากเกินไป เพราะจะซ่อนข้อผิดพลาดและนำไปสู่ความล้มเหลวที่ไม่คาดคิดใน production

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม