Search code examples
xcodeswiftuibarcode-scannerswift5

exc_breakpoint while trying to load view in SwiftUI


I'm trying to make barcode scanner app. I want the scanner to load as the app first launches, like a background. Then when a barcode is scanned, load a view on top displaying the product.

In my ContentsView() I load this View, which starts the scanner and then navigates to FoundItemSheet() when a barcode has been found.

import Foundation
import SwiftUI
import CodeScanner

struct barcodeScannerView: View {
    @State var isPresentingScanner = false
    @State var scannedCode: String?
    @State private var isShowingScanner = false


    var body: some View {
        NavigationView {
                if self.scannedCode != nil {
                    NavigationLink("Next page", destination: FoundItemSheet(scannedCode: scannedCode!), isActive: .constant(true)).hidden()
                }
        }
        .onAppear(perform: {
            self.isPresentingScanner = true
        })
        .sheet(isPresented: $isShowingScanner) {
            self.scannerSheet
        }
    }
    var scannerSheet : some View {
        CodeScannerView(
            codeTypes: [.qr],
            completion: { result in
                if case let .success(code) = result {
                    self.scannedCode = code
                    self.isPresentingScanner = false
                }
            }
        )
    }
}

When navigation view is replaced with a button, like this:

    VStack(spacing: 10) {
         if self.scannedCode != nil {
            NavigationLink("Next page", destination: FoundItemSheet(scannedCode: scannedCode!), isActive: .constant(true)).hidden()
          }
          Button("Scan Code") {
              self.isPresentingScanner = true
          }
          .sheet(isPresented: $isPresentingScanner) {
              self.scannerSheet
          }
          Text("Scan a QR code to begin")

It works with this solution, but I want the scanner to show when the app loads, not on a button press. I tried replacing the button with .onAppear with the same contents as the button, but it doesn't work.

This is foundItemSheet()

    struct FoundItemSheet: View {
    @State private var bottomSheetShown = false
    @State var scannedCode: String?

    var body: some View {
        GeometryReader { geometry in
            BottomSheetView(
                scannedCode: self.$scannedCode,
                isOpen: self.$bottomSheetShown,
                maxHeight: geometry.size.height * 0.7
            ) {
                Color.blue
            }
        }.edgesIgnoringSafeArea(.all)
        }

    }

struct FoundItemSheet_Previews: PreviewProvider {
    static var previews: some View {
        FoundItemSheet()
    }
}

I'm getting exc_breakpoint I believe where CodeScanner is declared.

I've been stuck on this for hours, so I'll reply quick to any questions.


Solution

  • Couple of thoughts..

    1) change order of modifiers

    .sheet(isPresented: $isShowingScanner) {
        self.scannerSheet
    }
    .onAppear(perform: {
        self.isPresentingScanner = true
    })
    

    2) make delayed sheet activation (as view hierarchy might not ready for that custom scanner view)

    .onAppear(perform: {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5)
           self.isPresentingScanner = true
        }
    })