Search code examples
swiftswiftuialert

Retry action not triggering alert again


I've been trying to create a function that can be retried after showing an alert, but for some reason the second time the function runs, the alert is not showing up. I would like to have the throwing function be rerun on the retry action.

import SwiftUI

struct SplashScreen: View {
    @State private var shouldPresentAlert = false

    var body: some View {
        ProgressView()
            .onAppear {
                performPotentiallyThrowingFunction()
            }
            .alert("Thrown", isPresented: $shouldPresentAlert) {
                Button("Retry", role: .cancel) {
                    performPotentiallyThrowingFunction()
                }
            } message: {
                Text("Something went wrong")
            }
    }

    private func performPotentiallyThrowingFunction() {
        do {
            throw URLError(.badURL)
        } catch {
            shouldPresentAlert = true
        }
    }
}

Solution

  • The alert isn't getting closed yet, so setting it to true again doesn't have any effect.

    To have it work as expected, you can close the Alert by setting shouldPresentAlert to false and then, on the next run loop or later, setting it to true

    struct SplashScreen: View {
        @State private var shouldPresentAlert = false
    
        var body: some View {
            ProgressView()
                .onAppear {
                    performPotentiallyThrowingFunction()
                }
                .alert("Thrown", isPresented: $shouldPresentAlert) {
                    Button("Retry", role: .cancel) {
                        shouldPresentAlert = false
                        Task {
                            performPotentiallyThrowingFunction()
                        }
                    }
                } message: {
                    Text("Something went wrong")
                }
        }
    
        private func performPotentiallyThrowingFunction() {
            do {
                throw URLError(.badURL)
            } catch {
                shouldPresentAlert = true
            }
        }
    }