Skip to content

Error Handling in SwiftUI

This tutorial covers creating a simple SwiftUI app that simulates data fetching with the possibility of encountering various errors. We’ll define a set of potential errors using an Enum, simulate a data fetch operation, and display alerts based on the error encountered.

Step 1: Define the DataError Enum

Start by defining an enum that lists various errors your data fetching operation might encounter.

enum DataError: Error {
    case fetchDataFailed
    case invalidData
    case networkError
    case unauthorizedAccess
}

Step 2: Create AlertItem and AlertContext Structures

Define AlertItem for alert details and AlertContext for storing predefined alerts for different error scenarios.

struct AlertContext {
    static let fetchDataFailed = AlertItem(
        title: Text("Fetch Data Failed"),
        message: Text("Unable to fetch data. Please try again."),
        dismissButton: .default(Text("OK"))
    )
    
    static let invalidData = AlertItem(
        title: Text("Invalid Data"),
        message: Text("The data received was invalid or corrupted. Please try again."),
        dismissButton: .default(Text("OK"))
    )
    
    static let networkError = AlertItem(
        title: Text("Network Error"),
        message: Text("There was a problem connecting to the network. Please check your internet connection and try again."),
        dismissButton: .default(Text("OK"))
    )
    
    static let unauthorizedAccess = AlertItem(
        title: Text("Unauthorized Access"),
        message: Text("You do not have permission to access this resource. Please check your credentials and try again."),
        dismissButton: .default(Text("OK"))
    )
}

Step 3: Simulate Data Fetching Function

Create a function to simulate a data fetching operation that randomly succeeds or fails, generating various errors.

func fetchData(completion: @escaping (Result<String, DataError>) -> Void) {
    let errorCases = [DataError.fetchDataFailed, .invalidData, .networkError, .unauthorizedAccess]
    let shouldSucceed = Bool.random()

    if shouldSucceed {
        completion(.success("Data fetched successfully!"))
    } else {
        let randomError = errorCases.randomElement()!
        completion(.failure(randomError))
    }
}

Step 4: Construct the SwiftUI View

Build a SwiftUI view that triggers the data fetching function and displays an alert based on the error encountered.

struct ErrorHandlingView: View {
    @State private var alertItem: AlertItem?

    var body: some View {
        VStack {
            Text("Tap to fetch data")
                .padding()
                .onTapGesture {
                    fetchData { result in
                        switch result {
                        case .success(let data):
                            print(data) // Process successful data fetch
                        case .failure(let error):
                            alertItem = alert(for: error) // Determine the appropriate alert
                        }
                    }
                }
        }
        .alert(item: $alertItem) { alertItem in
            Alert(title: alertItem.title, message: alertItem.message, dismissButton: alertItem.dismissButton)
        }
    }
    
  private func alert(for error: DataError) -> AlertItem {
        switch error {
     
        case .invalidData:
            return AlertContext.invalidData
            
        case .networkError:
            return AlertContext.networkError
            
        case .unauthorizedAccess:
            return AlertContext.unauthorizedAccess

        default:
            return AlertContext.fetchDataFailed // Placeholder for other errors
        }
    }
}

Conclusion

This tutorial provided a step-by-step approach to handling various error scenarios in a SwiftUI application. By defining a comprehensive DataError enum, simulating a data fetching operation, and using predefined alerts in AlertContext, you can effectively inform users about issues while maintaining a clean and organized codebase.

 

Back To Top