swift - 更改 @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 不再被解雇。
解决方案
我认为主要问题是应用程序可能会尝试使用四个不同的SystemServices
.
@StateObject
- '实例化可观察对象的属性包装器类型。'
@ObservedObject
- '订阅可观察对象并在可观察对象更改时使视图无效的属性包装器类型。
而不是@StateObject
,尝试@ObservedObject
在 App 的子视图中给予尝试。
祝你好运。
推荐阅读
- excel - VBA Excel 错误从同一数据库创建第二个数据透视表
- html - 如何为表单应用css
- python - 在 Django 中记录用户统计信息
- javascript - 如何根据服务器对数据进行分组并获取最新数据
- c++ - JNI 日期值转换问题,在 C++ 中获得不同的长值
- php - 从重写 htaccess 中排除文件和文件夹
- c# - 如何使用动态参数在 web.config 文件中设置重定向?
- c# - GET 和 POST 的 Asp.Net 文化不同
- android - 如何将 Material Button ShapeAppearance 与 Edittext Shape Appearance 分开?
- flutter - Flutter Provider:“ProxyFutureProvider”或类似的