Skip to Content

Error Handling trong Swift (try-catch)

1. Giới thiệu

Swift sử dụng throwing functions và do-catch để xử lý errors.

2. Định nghĩa Error

enum NetworkError: Error { case invalidURL case noConnection case timeout case serverError(code: Int) } enum ValidationError: Error { case emptyField(name: String) case invalidFormat }

3. Throwing Functions

func fetchData(from url: String) throws -> String { guard !url.isEmpty else { throw NetworkError.invalidURL } // Simulate network request return "Data from \(url)" }

4. do-catch

do { let data = try fetchData(from: "https://api.example.com") print(data) } catch NetworkError.invalidURL { print("Invalid URL") } catch NetworkError.noConnection { print("No internet connection") } catch { print("Unknown error: \(error)") }

5. try? - Optional Try

// Trả về nil nếu error let data = try? fetchData(from: "") print(data) // nil // Với nil coalescing let result = try? fetchData(from: url) ?? "Default"

6. try! - Force Try

// Crash nếu có error - dùng khi chắc chắn không lỗi let data = try! fetchData(from: "https://safe-url.com")

7. Propagating Errors

func processUser(id: Int) throws -> User { let data = try fetchData(from: "/users/\(id)") let user = try parseUser(from: data) return user }

8. LocalizedError

enum AppError: LocalizedError { case notFound case unauthorized var errorDescription: String? { switch self { case .notFound: return "Resource not found" case .unauthorized: return "You are not authorized" } } var failureReason: String? { switch self { case .notFound: return "The requested item does not exist" case .unauthorized: return "Invalid credentials" } } }

9. defer

func readFile(at path: String) throws -> String { let file = try openFile(at: path) defer { closeFile(file) print("File closed") } // Nếu error xảy ra, defer vẫn chạy let content = try readContent(from: file) return content }

10. Result Type

enum Result<Success, Failure: Error> { case success(Success) case failure(Failure) } func fetch(completion: (Result<String, NetworkError>) -> Void) { // Async operation... completion(.success("Data")) } fetch { result in switch result { case .success(let data): print("Got: \(data)") case .failure(let error): print("Error: \(error)") } }

11. Ví dụ thực tế

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, response) = try await URLSession.shared.data(from: url) guard let httpResponse = response as? HTTPURLResponse else { throw NetworkError.invalidURL } guard httpResponse.statusCode == 200 else { throw NetworkError.serverError(code: httpResponse.statusCode) } return try JSONDecoder().decode(User.self, from: data) }

📝 Tóm tắt

  • throws đánh dấu function có thể throw error
  • try gọi throwing function
  • do-catch xử lý errors
  • try? returns optional
  • try! force unwrap (crash nếu error)
  • defer chạy code trước khi thoát scope
  • Result type cho async callbacks
Last updated on