SwiftUI使数据脱离协调器进入内容视图

时间:2019-10-17 17:24:22

标签: swift uikit swiftui

我正在将QR码阅读器内置到我的应用中,到目前为止,我将其作为工作表打开,并在检测到QR /条形码时关闭。 该应用程序的阅读器部分使用UIKit,我有一个文件QRCodeScan.swift,它是UIViewControllerRepresentable,qr扫描程序将找到的代码值返回到此文件的协调器中。 我似乎找不到任何方法将找到的代码从协调器中移到原始视图中。

这是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
        }

    }
}

这是ContentView的简化版本,称为qr阅读器,这是我需要在其中找到找到的代码的地方

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")
            })
        }
    }
}

我在这里遇到了一个总障碍,我找不到任何资源可以让我从协调器传回数据,也许我实现了错误,但是我似乎无法适应任何其他解决方案适合

非常感谢您的帮助。

谢谢

2 个答案:

答案 0 :(得分:1)

我已经在以下答案中为您回答过:SwiftUI go back programmatically from representable to View

  

或者,您也可以通过在QRCodeScan上创建一个闭包(由代码调用)来关闭演示者。

编辑:我已经将我的建议插入您的代码中,向您展示谁拥有什么以及如何传递信息。

struct QRCodeScan: UIViewControllerRepresentable {

    /// a closure called with the found code
    var onCodeScanned: (String) -> Void

    class Coordinator: NSObject, QRCodeScannerDelegate {

        func codeDidFind(_ foundCode: String) {
            // call the parent's `onCodeScanned` closure here
            parent.onCodeScanned(foundCode)

            presentationMode.wrappedValue.dismiss()
        }

        var parent: QRCodeScan

        // init, makeViewController, etc.
    }
}
  

和演示者中

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){
                        // when you create the VC representable, pass in your closure to handle found codes
                        QRCodeScan(onCodeScanned: {
                            self.processFoundCode($0)
                        })
                    }
                }

            }
            // .theRest()
        }
    }

    func processFoundCode(_ code: String) {
        // process it

        // dimiss sheet
        presentQRScanned = false
    }
}

换句话说,闭包将把数据沿链传递到您的ContentView

答案 1 :(得分:1)

您可能已经解决了此问题,但是解决方案是在ContentView中使用@State变量,该变量链接到QRCodeScan Struct和Coordinator类中的@Binding变量。

查看以下答案:Accessing MKMapView elements as UIViewRepresentable in the main (ContentView) SwiftUI view

像这样的东西应该可以解决问题,但是我建议阅读我链接的更详细的答案:

 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
    }
}
}

在ContentView中,创建@State var代码,然后可以调用QRCodeScan(代码:$ code)。