首页 > 解决方案 > 更改 @Published 值会在视图中触发 Init

问题描述

我在初始化视图时遇到问题,在设置 @Published 属性时它会重新初始化,我不知道为什么。

应用结构为:MyApp -> MainView -> fullscreenCover OrderView -> ListOfOrders -> fullscreenCover ProductView -> Bug Button。视图模型被注入为@StateObject。

这是我正在开发的应用程序的简化版本:

查看模型

class SystemService: ObservableObject {
  @Published private(set) var testValue: Bool = false
  @Published private(set) var products: [Product] = []
}

应用声明

@main
struct MyApp: App {
  @StateObject private var systemService = SystemService()

  @ViewBuilder
  var body: some Scene {
    WindowGroup {
      MainView(systemService: systemService)
    }
  }
}

主视图,基本上只显示全屏模式视图 - OrderView

struct MainView: View {
  @StateObject var systemService: SystemService
  @State private var activeFullScreen: ActiveFullScreenEnum?

  var body: some View {
    VStack {
      Button(action: {
        activeFullScreen = .order
      }, label: Text("Order Details"))
    }
    .fullScreenCover(item: $activeFullScreen, content: { item in
      switch item {
      case .order:
        OrderView(systemService: systemService)
      }
    })
  }
}

订单视图包含产品列表。

 struct OrderView: View {
      @StateObject var systemService: SystemService
      @State private var activeFullScreen: OrderFullScreenEnum?
    
      init(systemService: SystemService) {
        _systemService = StateObject(wrappedValue: systemService)
    
        print("OrderScreen Initialized")
      }
    
      var body: some View {
        VStack {
          ScrollView {
            ForEach(systemService.products) { product in
              Button(action: {
                activeFullScreen = .product(product)
              }, label: Text("Prodcut Details"))
            }
          }
        }
        .fullScreenCover(item: $activeFullScreen, content: { item in
          switch item {
          case .product(let product):
            ProductView(systemService: systemService, product: product)
          }
        })
      }
    }

最后是发现错误的产品视图。

错误是 - 当按下“错误按钮”时,ProductView被关闭,并且 OrderView 的 init 调用并打印出“OrderScreen Initialized”。

struct ProductView: View {
  @StateObject var systemService: SystemService

  var body: some View {
    VStack {
      Button(action: {
        systemService.testValue.toggle()
      }, label: Text("Bug Button"))
    }
  }
}

可能是我对Combine如何工作的根本误解的问题,如果有人可以提供帮助,我将不胜感激。

***** 附加信息 *****

如果我添加.onAppear到订单视图

 .onAppear {
      print("Order View Did Appear")
    }

systemService.testValue.toggle()从 Ordre View 触发的第一次调用.onAppear,但只有一次,只有第一次。之后,该错误消失并且 .fullScreenCover 不再被解雇。

标签: swiftswiftuicombine

解决方案


我认为主要问题是应用程序可能会尝试使用四个不同的SystemServices.

@StateObject- '实例化可观察对象的属性包装器类型。'

@ObservedObject- '订阅可观察对象并在可观察对象更改时使视图无效的属性包装器类型。

而不是@StateObject,尝试@ObservedObject在 App 的子视图中给予尝试。

祝你好运。


推荐阅读