提问者:小点点

更改@published时重新加载视图


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

当我用@ObserveableObject更新“barcode”变量时,它不会用条形码中的数据更新视图。

内容视图

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

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

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

Scanner视图-scannedCode链接到@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条形码变量,所以当它改变时,我希望contentsInSlide用新的条形码重新加载。

    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个答案

匿名用户

问题是您的所有视图都创建自己的ScanneDCode实例。 您只需要在创建所有其他视图的类型上创建它,并将相同的实例注入到每个视图中。

从您的代码片段来看,并不清楚哪个视图是哪个视图的父视图,因此很难通过代码示例给出明确的答案,但是通常,您永远不应该在视图本身中创建@observableobject,因为一旦重新加载视图,该对象就会重新创建。 相反,您应该在视图模型或父视图上创建@observableobject,并将其注入到需要重新加载的子视图中。

使用下面的代码,每当更新parentview上的scanneDcode时,它将用更新的scanneDcode重新加载其childview

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