0

I am trying to figure out how to display errors such as those found in the App Store Store class and Persistence.swift file in a single reporting module. Some of my errors within views use an environment object to tie the error production to the error reporting, but this isn’t feasible with errors in different classes.

So any pointers on handling these types of errors would be much appreciated.

Below is an example of my process to report an error within a view

// the save button has been pressed
struct saveButton: View {

     @Environment(\.managedObjectContext) var viewContext
     @EnvironmentObject var errorHandling: ErrorHandling

     var body: some View {

     // prepping data for save to core data


        do {
                try viewContext.save()

            } catch {
                // report: Unable to Save Transaction
                self.errorHandling.handle(error: AppError.saveTransactionError)
            }

The App Store purchase method (below) may produce two errors that I would like to display with my app. This is the type of logic that I need help display the error within a view

@MainActor
    func purchase() {

        Task.init {

            guard let product = products.first else {
                return
            }

            guard AppStore.canMakePayments else {
                return
            }

            do {
                let result = try await product.purchase()
                switch result {
                case .success(let verification):
                    
                    switch verification {
                        
                    case .verified(let transaction):
                        await transaction.finish()

                        // save to user defaults
                        self.purchasedIds = transaction.productID
                        break

                    case .unverified:
                        // throw PurchaseError.failed
                        // FIX: report error (Unable to purchase verification failed)
                        break 
                    }
                    break

                case .userCancelled:
                    break

                    // asked to buy (setting on phone prevents purchases)
                case .pending:
                    break

                default:
                    break
                }
            }
            catch {
                print(error.localizedDescription)
                // FIX: report error (Unable to Complete Purchase)
            }
        }
    }
enum AppError: LocalizedError {
    case storePurchaseError
    case storeVerificationError

 
var errorDescription: String? {
        switch self {
        case .storePurchaseError: 
            return NSLocalizedString("Store Purchase Error", comment: "")

        case .storeVerificationError:
            return NSLocalizedString("Store Verification Error", comment: "")
      }
   }
}

Below is some code I have been using to display an alert

struct ErrorAlert: Identifiable {
    var id = UUID()
    var message: String
    var dismissAction: (() -> Void)?
}

class ErrorHandling: ObservableObject {
    @Published var currentAlert: ErrorAlert?

    func handle(error: Error) {
        currentAlert = ErrorAlert(message: error.localizedDescription)
    }
}

struct HandleErrorsByShowingAlertViewModifier: ViewModifier {
    @StateObject var errorHandling = ErrorHandling()

    func body(content: Content) -> some View {
        content
            .environmentObject(errorHandling)
            .background(
                EmptyView()
                    .alert(item: $errorHandling.currentAlert) { currentAlert in
                        Alert(
                            title: Text("Error"),
                            message: Text(currentAlert.message),
                            dismissButton: .default(Text("Ok")) {
                                currentAlert.dismissAction?()
                            }
                        )
                    }
            )
    }
}

extension View {
    func withErrorHandling() -> some View {
        modifier(HandleErrorsByShowingAlertViewModifier())
    }
}
2
  • this this isn’t a full answer but it is an approach. I use one alert for all my errors. Always throw them as far as possible and then send them to a log manager where presenting analytics and logging is done. Commented Oct 29, 2022 at 11:13
  • Thanks @lorem ipsum for your input. I have been looking at several logging ideas for possible use in my app Commented Nov 1, 2022 at 20:57

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.