Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI getting data out of coordinator into content view

I'm building a QR code reader into my app, so far I have it open as a sheet and close when a qr/barcode is detected. The reader part of the app uses UIKit, I have the file QRCodeScan.swift which is the UIViewControllerRepresentable, the qr scanner returns the value of the code that it has found into the coordinator in this file. I can't seem to find any way to get the found code out of the coordinator into the original view.

This is the file QRCodeScan.

struct QRCodeScan: UIViewControllerRepresentable {

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIViewController(context: Context) -> ScannerViewController {
        let vc = ScannerViewController()
        vc.delegate = context.coordinator
        return vc
    }

    func updateUIViewController(_ vc: ScannerViewController, context: Context) {
    }

    class Coordinator: NSObject, QRCodeScannerDelegate {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

        func codeDidFind(_ foundCode: String) {
            print(foundCode)
            /*this is where the code comes to, need to return it from here */
            presentationMode.wrappedValue.dismiss()
        }

        var parent: QRCodeScan

        init(_ parent: QRCodeScan) {
            self.parent = parent
        }

    }
}

This is a cropped down version of the ContentView that calls the qr reader , this is where I need to get the found code back into

struct ContentView: View {

    @State var presentQRScanner = false

    var body: some View {
        NavigationView{
            Form{
                Section(header: Text("Info")){
                    Button("Scan Barcode"){
                        self.presentQRScanner = true
                    }
                        .sheet(isPresented: $presentQRScanner){QRCodeScan()}
                }

            }

            .navigationBarTitle(Text("New"), displayMode: .large)
            .navigationBarItems(trailing: Button("Save"){
                print("Button Pressed")
            })
        }
    }
}

I've hit a total roadblock here, I can't find any resources that allow me to pass the data back from the coordinator, maybe I'm implementing something wrong but I can't seem to adapt any other solutions to fit

Any help is much appreciated.

Thanks

like image 481
robbo5899 Avatar asked Oct 17 '19 17:10

robbo5899


People also ask

Is it possible to use coordinator pattern with SwiftUI?

However, with SwiftUI released roughly two and a half years ago and maturing ever since, the question arises of how to use the Coordinator pattern with SwiftUI. It turns out that it’s not as easy as replacing all the UIKit views (and view controllers) with their SwiftUI equivalents.

How to get data from contentview to secondview in SwiftUI?

Since all Views in SwiftUI are struct, we can add a Writer property to SecondView without providing an initial value. You will use this property to receive the data from ContentView.

How do I use core data in SwiftUI?

Use SwiftUI’s data flow to access what you need in the Core Data framework. Define and create new model objects using Core Data. Use Fetch Requests to retrieve objects from disk. So buckle up and learn more about Core Data’s capabilities and how it works!

How to transfer data from parent to child in SwiftUI?

In this article, we will study all the available options, and look at some best practices regarding when you should use which mechanism. The most common way of transferring data in SwiftUI is from a parent view to its direct child. The parent just instantiates the child and passes data to its initializer.


Video Answer


1 Answers

You may have already solved this, but the solution is to use an @State variable in your ContentView linked to an @Binding variable in your QRCodeScan Struct and the Coordinator Class.

Check out this answer: Accessing MKMapView elements as UIViewRepresentable in the main (ContentView) SwiftUI view

Something like this should do the trick, but I suggest reading over the more detailed answer I linked:

 struct QRCodeScan: UIViewControllerRepresentable {

    @Binding var code: String

func makeCoordinator() -> Coordinator {
    return Coordinator(code: $code)
}

func makeUIViewController(context: Context) -> ScannerViewController {
    let vc = ScannerViewController()
    vc.delegate = context.coordinator
    return vc
}

func updateUIViewController(_ vc: ScannerViewController, context: Context) {
}

class Coordinator: NSObject, QRCodeScannerDelegate {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

   @Binding var code: String

   init(code: Binding<String>) {
   _code = code
   }

    func codeDidFind(_ foundCode: String) {
        print(foundCode)
        /*this is where the code comes to, need to return it from here */
        self.code = foundCode
        presentationMode.wrappedValue.dismiss()
    }

    var parent: QRCodeScan

    init(_ parent: QRCodeScan) {
        self.parent = parent
    }
}
}

In your ContentView, create @State var code, then you can call QRCodeScan(code: $code).

like image 73
lmh Avatar answered Oct 14 '22 00:10

lmh