Handling Errors Gracefully in Swift
Error handling is one of the most important yet overlooked aspects of app development. Let’s explore best practices for Swift.
The Problem with Silent Failures
Nothing frustrates users more than an app that fails silently. “Something went wrong” messages are unhelpful.
Swift’s Error Handling
Swift provides a robust error handling system:
enum NetworkError: Error {
case invalidURL
case noData
case decodingError
case serverError(Int)
var localizedDescription: String {
switch self {
case .invalidURL:
return "The URL is invalid."
case .noData:
return "No data received from the server."
case .decodingError:
return "Failed to process the response."
case .serverError(let code):
return "Server error: \(code)"
}
}
}
Using Result Type
For more flexible error handling:
func fetchUser(id: Int) async -> Result<User, NetworkError> {
do {
let user = try await api.getUser(id: id)
return .success(user)
} catch let error as NetworkError {
return .failure(error)
} catch {
return .failure(.decodingError)
}
}
User-Friendly Error Messages
func handleError(_ error: NetworkError) -> String {
switch error {
case .invalidURL:
return "Please check your internet connection and try again."
case .noData:
return "We're having trouble loading data. Pull to refresh."
case .decodingError:
return "Please update the app to the latest version."
case .serverError:
return "Our servers are busy. Please try again in a few minutes."
}
}
Good error handling turns frustration into trust. Users appreciate honesty and clarity.