【发布时间】:2020-09-14 12:30:10
【问题描述】:
在 SwiftUI 中,我创建了一个结构,它应该根据一些状态变量创建不同的覆盖视图。如果任何状态布尔值为真,那么它应该返回自定义视图(ErrorOverlay 或 LoadingOverlay 或 EmptyView),如下所示:
struct OverlayContainer: View {
@State var isLoading: Bool = false
@State var isErrorShown: Bool = false
func setIsLoading(isLoading: Bool) {
self.isLoading = isLoading
}
func setIsErrorShown(isErrorShown: Bool) {
self.isErrorShown = isErrorShown
}
var body: some View {
Group {
if(isErrorShown) {
ErrorOverlay()
}
else if(isLoading) {
LoadingOverlay()
}
else {
EmptyView()
}
}
}
}
现在我已经在 Home 视图中的某些内容上实现了覆盖,其中的按钮应该会改变状态并显示正确的覆盖,如下所示:
struct Home: View {
var body: some View {
let overlayContainer = OverlayContainer()
return HStack {
// Some more content here
Button(action: {
overlayContainer.setIsLoading(isLoading: true)
}) {
Text("Start loading")
}
Button(action: {
overlayContainer.setIsErrorShown(isErrorShown: true)
}) {
Text("Show error")
}
}.overlay(overlayContainer)
}
}
这不起作用:当我单击按钮时,什么也没有发生。为什么以及如何解决这个问题? (不使用绑定,见下文)
ps。通过执行以下操作,我已经能够获得有效的解决方案:
- 将状态布尔值提取到主页视图
- 通过 OverlayContainer 的构造函数传递这些
- 单击按钮时更改状态布尔值而不是调用 set 方法
- 更改 OverlayContainer,使其实现一个带有两个布尔值的
init方法 - 将 OverlayContainer 中的状态布尔值更改为绑定。
但是,我想实现 OverlayContainer 中的状态,以便能够在不同的屏幕中重新使用它,而无需在所有这些屏幕中实现状态变量。首先是因为可能会有比这 2 种更多的情况。其次因为不是所有的屏幕都需要访问所有的状态,而且我还没有找到一种通过 init 方法实现可选绑定的简单方法。
在我看来,所有这些状态都属于 OverlayContainer,并且更改状态应该尽可能短且干净。到处定义状态感觉就像代码重复。也许我需要一个完全不同的架构?
【问题讨论】:
-
您找到解决方案了吗?我有同样的问题,下面的建议不能满足您将状态保持在“内部”对象内的要求......
标签: swiftui