Bỏ qua để đến nội dung

Error Handling

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

enum NetworkError: Error {
case invalidURL
case noConnection
case timeout
case serverError(code: Int)
}
enum ValidationError: Error {
case emptyField(name: String)
case invalidFormat
}
func fetchData(from url: String) throws -> String {
guard !url.isEmpty else {
throw NetworkError.invalidURL
}
// Simulate network request
return "Data from \(url)"
}
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)")
}
// 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"
// 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")
func processUser(id: Int) throws -> User {
let data = try fetchData(from: "/users/\(id)")
let user = try parseUser(from: data)
return user
}
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"
}
}
}
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
}
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)")
}
}
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)
}

  • 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