在SwiftUI中,我创建了一个结构,该结构应根据某些状态变量创建不同的覆盖视图。如果任何状态布尔值都为true,则它应返回自定义视图(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()
}
}
}
}
现在,我已经在主视图中的某些内容上实现了叠加层,该按钮应该会更改状态并显示正确的叠加层,例如:
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。通过执行以下操作,我已经获得了可行的解决方案:
init
方法但是,我想在OverlayContainer中实现状态,以便能够在不同的屏幕中重复使用状态,而无需在所有这些屏幕中都实现状态变量。首先,因为可能会有比这2更多的情况。其次,因为并非所有屏幕都需要访问所有状态,而且我还没有找到通过init方法实现可选绑定的简单方法。
在我看来,所有这些状态都属于OverlayContainer,并且更改状态应尽可能短而整洁。到处定义状态就像代码重复一样。也许我需要一个完全不同的体系结构?
答案 0 :(得分:0)
应改为使用绑定。这是可能的解决方案。
struct OverlayContainer: View {
@Binding var isLoading: Bool
@Binding var isErrorShown: Bool
var body: some View {
Group {
if(isErrorShown) {
ErrorOverlay()
}
else if(isLoading) {
LoadingOverlay()
}
else {
EmptyView()
}
}
}
}
struct Home: View {
@State var isLoading: Bool = false
@State var isErrorShown: Bool = false
var body: some View {
HStack {
// Some more content here
Button(action: {
self.isLoading = true
}) {
Text("Start loading")
}
Button(action: {
self.isErrorShown = true
}) {
Text("Show error")
}
}.overlay(OverlayContainer(isLoading: $isLoading, isErrorShown: $isErrorShown))
}
}
答案 1 :(得分:0)
要使其成为您想要的方式,请使用Binding:
struct OverlayContainer: View {
@Binding var isLoading: Bool
@Binding var isErrorShown: Bool
func setIsLoading(isLoading: Bool) {
self.isLoading = isLoading
self.isErrorShown = !isLoading
}
func setIsErrorShown(isErrorShown: Bool) {
self.isErrorShown = isErrorShown
self.isLoading = !isErrorShown
}
var body: some View {
Group {
if(isErrorShown) {
ErrorOverlay()
}
else if(isLoading) {
LoadingOverlay()
}
else {
EmptyView()
}
}
}
}
struct Home: View {
@State var isLoading = false
@State var isErrorShown = false
var body: some View {
let overlayContainer = OverlayContainer(isLoading: $isLoading, isErrorShown: $isErrorShown)
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)
}
}