quanshousio/ToastUI

Can't present subsequent toast without using onDismiss on the first toast

roddymunro opened this issue ยท 3 comments

Pre-requisites:

  • [] Yes, I looked through both open and closed issues looking for what I needed
  • No, I did not find what I was looking for

I want to be able to display either a SuccessToastViewStyle or an ErrorToastViewStyle once my network request has finished.

The ShowSuccessToastAfterCompletedExample in the example project works great, however my case is a little bit different. I make a network call which shows an indefinite alert. At the end of the request, it calls my completion handler and passes a Result. If there is a .success, I want to display a success alert, and if there is a .failure, I'll display an error alert.

Example code:

CustomButton("Tap me") {
    savingViewShowing = true

    model.makeNetworkRequest() { result in
        switch result {
            case .success:
                savingViewShowing = false
                showSuccessAlert = true
            case .failure:
                savingViewShowing = false
                showErrorAlert = true
        }
    }
}
.toast(isPresented: $savingViewShowing) {
    ToastView("Saving...")
        .toastViewStyle(IndefiniteProgressToastViewStyle())
}
.toast(isPresented: $showSuccessAlert, dismissAfter: 1.0, onDismiss: { resetForm() }) {
    ToastView("Success!")
        .toastViewStyle(SuccessToastViewStyle())
}
.toast(isPresented: $showErrorAlert, dismissAfter: 1.0) {
    ToastView("Error!")
        .toastViewStyle(ErrorToastViewStyle())
}

However, the above doesn't work. The "Saving" alert will show fine, but nothing will show after that.

Changing my "Saving" alert's onDismiss to set showSuccessAlert to true does work:

.toast(isPresented: $savingViewShowing, onDismiss: { showSuccessAlert = true }) {
    ToastView("Saving...")
        .toastViewStyle(IndefiniteProgressToastViewStyle())
}

This isn't great when I don't know at build time which alert to show in my completion handler. I could create a lot of extra @States that hold success/fail, but that isn't ideal.

Is there something I'm doing wrong, or is there something that can be fixed?

Your Environment

  • Swift Version: 5
  • Xcode Version: 12 beta 4
  • Operating System and Version: iOS 14 beta 4
  • Device or Simulator: Simulator and device

not the prettiest solution but how about:

CustomButton("Tap me") {
    savingViewShowing = true

    model.makeNetworkRequest() { result in
        self.result = result    
    }
}
.toast(isPresented: $savingViewShowing, onDismiss: { 
    switch self.result {
        case .success:
            showSuccessAlert = true 
        case .error:
            showErrorAlert = true
    }
}) ) {
    ToastView("Saving...")
        .toastViewStyle(IndefiniteProgressToastViewStyle())
}
.toast(isPresented: $showSuccessAlert, dismissAfter: 1.0, onDismiss: { resetForm() }) {
    ToastView("Success!")
        .toastViewStyle(SuccessToastViewStyle())
}
.toast(isPresented: $showErrorAlert, dismissAfter: 1.0) {
    ToastView("Error!")
        .toastViewStyle(ErrorToastViewStyle())
}

In the initial example, it's because the spinner view hasn't finished its dismiss when you set the binding boolean to false but you show the success/error alert right after that in your completion handler.

The solution is arguably not the prettiest one but it works in the way I expected. I also tried toast(item:onDismiss:content:) but it failed to do what you're trying to accomplish here. Nevertheless, I will try to come up with a better way to show different toasts with different onDismiss callbacks in the future.

@quanshousio Thank you for the explanation!

@LucasCarioca Awesome, that works and I'm happy to run with that. Thank you!