Navigation link not working when adding Activity loader for API Call SwiftUI

96 Views Asked by At

In my SwiftUI application, I have a form with Textfields and a Button in the last section. The last section of the form is as below:

NavigationLink(destination: PreviewOrderView(placeOrderObj: placeOrder, deliveryCharge: deliveryCharge), isActive: $showPreview) {
    EmptyView()
}.frame(width: 0, height: 0)
 .opacity(0)

Button("PROCEED") {
    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    validateFields()
    if !showErrorAlert {
        isLoading = true
        Task {
            await fetchDeliveryCharge()
        }
    }
}.buttonStyle(RoundedGreenButton(enable: true))

After getting a successful response, the binding value for the navigation is set as True. This is in the function:

func fetchDeliveryCharge() async {
    let params = ["userId": placeOrder.userId ?? "",
                  "locationType":"AreaName",
                  "locationName":placeOrder.areaName ?? "",
                  "mLatitude":placeOrder.mLatitude ?? 0.0,
                  "mLongitude":placeOrder.mLongitude ?? 0.0,
                  ] as [String : Any]
    APIManager.shared.getDeliveryChargeDetails(dict: params) { response in
        if response.Results.status {
            DispatchQueue.main.async {
                showPreview = true
                isLoading = false
            }
        } else {                    
        }
    } errorHandler: { error in
        isLoading = false
    }
}

For the activity loader, I am using:

struct ActivityIndicator: UIViewRepresentable {
    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style

    func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: style)
    }

    func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}

struct ActivityIndicatorModifier: AnimatableModifier {
    var isLoading: Bool

    init(isLoading: Bool, color: Color = .primary, lineWidth: CGFloat = 3) {
        self.isLoading = isLoading
    }

    var animatableData: Bool {
        get { isLoading }
        set { isLoading = newValue }
    }

    func body(content: Content) -> some View {
        ZStack {
            if isLoading {
                GeometryReader { geometry in
                    ZStack(alignment: .center) {
                        content
                            .disabled(self.isLoading)
                            .blur(radius: self.isLoading ? 3 : 0)

                        VStack {
                            Text("Loading...")
                            ActivityIndicator(isAnimating: .constant(true), style: .large)
                        }
                        .frame(width: geometry.size.width / 2,
                               height: geometry.size.height / 5)
                        .background(Color.secondary.colorInvert())
                        .foregroundColor(Color.primary)
                        .cornerRadius(20)
                        .opacity(self.isLoading ? 1 : 0)
                        .position(x: geometry.frame(in: .local).midX,
                                  y: geometry.frame(in: .local).midY)
                    }
                }
            } else {
                content
            }
        }
    }
}

To show the activity loader, I am using the modifier .modifier(ActivityIndicatorModifier(isLoading: isLoading)). The issue is that after getting the API response, the loader is removed, but the navigation to the next screen is not happening. The form is scrolled to the top and if I scroll down, it will automatically navigate to the next screen. Please help me find the reason for this behavior.

0

There are 0 best solutions below