更改@Published时重新加载视图 [英] Reload view when @Published is changed

查看:43
本文介绍了更改@Published时重新加载视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to be able to scan barcodes, then show the barcode at the bottom of the screen in a sheet, or a separate view.

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

When I update the 'barcode' variable which is @Published and accessed in other methods with @ObserveableObject, it doesn't update the view with the data from the barcode.

内容视图

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

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

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

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

Scanner View - scannedCode is linked to the @Published variable, so when this changes, I want it to reload FoundItemSheet() as a barcode has been found by the scanner

    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,该视图显示在屏幕底部相机上方的框中.我希望它随条形码数据一起更新.

FoundItemSheet() Loads BottomSheetView which is shown at the bottom of the screen in a box over the camera. I want this to update with the barcode data when it's found.

        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重新加载新的条码.

BottomSheetView - I have declared the @Published barcode variable in here, so when it changes, I want contentsInSlide to reload with the new barcode.

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

推荐答案

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

The problem is that all of your views create their own ScannedCode instances. You need to create it only on the type that creates all other views and inject the same instance into each one of them.

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

From your code snippets it isn't really clear which view is the parent of which, so it's hard to give you a definitive answer with a code example, but in general, you should never create an @ObservableObject in a view itself, since that object will be recreated as soon as the view is reloaded. Instead, you should be creating your @ObservableObject on the view model or the parent view and injecting it into the child view that needs reloading.

使用以下代码,每当更新 ParentView 上的 scannedCode 时,它将使用更新的 ScannedCode ChildView >.

Using below code, whenever scannedCode on the ParentView is updated, it reloads its ChildView with the updated 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)
    }
}

这篇关于更改@Published时重新加载视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆