@Published更改时重新加载视图

时间:2020-06-25 10:58:38

标签: ios swift swiftui

我希望能够扫描条形码,然后在工作表或单独视图的屏幕底部显示条形码。

当我使用其他方法通过@ObserveableObject更新@published并通过其他方法访问的“条形码”变量时,它不会使用条形码中的数据更新视图。

内容视图

class ScannedCode: ObservableObject {
    @Published var barcode = ""
}

struct ContentView: View {
    @ObservedObject var barcode = ScannedCode()

    var body: some View {
        ZStack {
            ScannerView()
            FoundItemSheet()
        }
    }
}

扫描器视图-scanCode链接到@Published变量,因此当此更改时,我希望它重新加载FoundItemSheet(),因为扫描器已找到条形码

    class Coordinator: BarcodeScannerCodeDelegate, BarcodeScannerErrorDelegate {
    @ObservedObject var scannedCode = ScannedCode()
    
    private var scannerView: ScannerView

    init(_ scannerView: ScannerView) {
        self.scannerView = scannerView
    }
    
    func scanner(_ controller: BarcodeScannerViewController, didCaptureCode code: String, type: String) {
        self.scannedCode.barcode = code
        controller.resetWithError(message: "Error message")
    }

    func scanner(_ controller: BarcodeScannerViewController, didReceiveError error: Error) {
      print(error)
    }
}

FoundItemSheet()加载BottomSheetView,该视图显示在屏幕底部相机上方的框中。我希望它随条形码数据一起更新。

        struct FoundItemSheet: View {
        @State private var bottomSheetShown = false
        
        var body: some View {
            GeometryReader { geometry in
                BottomSheetView(
                    isOpen: self.$bottomSheetShown,
                    maxHeight: geometry.size.height * 0.7
                ) {
                    Color.blue
                }
            }.edgesIgnoringSafeArea(.all)
            }
        }

BottomSheetView -我在这里声明了@Published条码变量,因此当它发生变化时,我希望contentInSlide重新加载新的条码。

    struct BottomSheetView<Content: View>: View {
       @Binding var isOpen: Bool
       @State var showingDetail = false
       @ObservedObject var scannedCode = ScannedCode()

     ....
        private var contentInSlide: some View {
        VStack {
                Text("Value is: \(scannedCode.barcode)") //Doesn't show any value for the barcode
                    .foregroundColor(ColorManager.beautytruthGreen)
                    .font(.system(size: 22, weight: .medium))
                Button(action: {
                    self.showingDetail.toggle()
            }
        }

1 个答案:

答案 0 :(得分:1)

问题是您所有的视图都创建了自己的ScannedCode实例。您只需在创建所有其他视图的类型上创建它,然后将相同的实例注入其中的每个视图即可。

从代码片段中并不清楚哪个视图是哪个视图的父视图,因此很难通过代码示例为您提供明确的答案,但是通常,您绝对不应在其中创建一个@ObservableObject视图本身,因为将在重新加载视图后立即重新创建该对象。相反,您应该在视图模型或父视图上创建@ObservableObject,并将其注入需要重新加载的子视图中。

使用以下代码,每当scannedCode上的ParentView被更新时,它就会使用更新后的ChildView重新加载其ScannedCode

struct ParentView: View {
    @Published var scannedCode = ScannedCode()

    var body: some View {
        ChildView(scannedCode: scannedCode)
    }
}

struct ChildView: View {
    @ObservedObject var scannedCode: ScannedCode

    var body: some View {
        Text(scannedCode.barCode)
    }
}