Search code examples
swiftuicameraalert

SwiftUI - How to show an alert after QR code is scanned


I need to show an alert when a QR code is scanned. If the correct QR code is scanned, then lets say "Correct" alert needs to be shown, "InCorrect" otherwise.

Following is the code which I tried using.

Disclaimer - Am not an expert in SwiftUI but have been coding for quite a few years and about an year on SwiftUI. I may also have some gaps in understanding SwiftUI which I am trying to clear.


    @Published var showingAlert = false
    
    
    Button(action: {
        showCameraForQR = true
    }, label: {
        Image ("QRCodeIcon")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .foregroundColor(Color.gray.opacity(0.5))
    }).frame(width: 30, height: 30, alignment: .center)
        .padding(.top,5)
        .padding(.bottom,15)
        .padding(.leading,5)
        .padding(.trailing,5)
        .sheet(isPresented: $showCameraForQR) {
            CodeScannerView(codeTypes: [.qr], completion: handleScan)
        }
        .alert(isPresented: $showingAlert) {
            Alert(title: Text(titleOfAlert))
        }
    
    
    func handleScan(result: Result<ScanResult, ScanError>) {
        showCameraForQR = false
        // Code to set the title.
        titleOfAlert = "Correct"
        // Trigger showing of alert now
        showingAlert = true
    }

When I execute this code, after the camera opens and QR code is scanned, the following log is seen in the logger but no Alert message:

Attempt to present <SwiftUI.PlatformAlertController: 0x104808e00> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x102018800> (from <_TtGC7SwiftUI32NavigationStackHostingControllerVS_7AnyView_: 0x1021dae00>) which is already presenting <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x1022c7000>.

I believe, the sheet is not getting closed before the Alert is invoked. So, how do I close the sheet before the alert is invoked ?

Note, I am using CodeScanner 2.3.3.


Solution

  • You could try this approach, where you set showingAlert = true when you dismiss the .sheet, instead of setting it in your func handleScan. For example using:

    // ---- here
    .sheet(isPresented: $showCameraForQR, onDismiss: {showingAlert = true}) {...}
    
    func handleScan(result: Result<ScanResult, ScanError>) {
        // Code to set the title.
        titleOfAlert = "Correct"
        showCameraForQR = false
        // NO `showingAlert = true` <---- here
    }
     
    

    The showCameraForQR = false in handleScan will dismiss the .sheet, and the onDismiss: {showingAlert = true} will popup the Alert afterwards.