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 errortrygọi throwing functiondo-catchxử lý errorstry?returns optionaltry!force unwrap (crash nếu error)deferchạy code trước khi thoát scope- Result type cho async callbacks
Last updated on
Swift