我制作了一个自定义 ViewModifier,例如“进度栏”(但在下面的代码中,例如,我仅使用不同的背景颜色。
我有一个从 API 下载数据的功能(例如,在下面的代码中,我使用延迟 3 秒的“假”下载。
我使用布尔变量来检查是否正在加载。
我的问题是,为什么我要写
.进展 .onAppear {下载函数}
一切都好,但如果我改变顺序
.onAppear {下载函数} .进度
这将是无尽的“进步”,我的主视图将永远不会显示。
我需要理解为什么会发生这种情况,以及为什么其他顺序一切都好。
struct ContentView: View {
@State private var isLoaded = true
var body: some View {
ZStack {
Color.blue
.ignoresSafeArea()
Text("Example")
.foregroundStyle(.white)
.font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
.bold()
}
.onAppear { fakeNetworkCall() }
.progress(isLoaded: isLoaded)
}
func fakeNetworkCall() {
DispatchQueue.main.asyncAfter(deadline: .now() + 3 ) {
isLoaded = false
}
}
}
struct LoadingView: ViewModifier {
var isLoaded : Bool
func body(content: Content) -> some View {
if isLoaded {
ZStack {
Color.red
.ignoresSafeArea()
Text("Example")
.foregroundStyle(.white)
.font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
.bold()
}
} else {
content
}
}
}
extension View {
func progress(isLoaded: Bool) -> some View {
modifier(LoadingView(isLoaded: isLoaded))
}
}
当我悲伤时,如果我会改变
.progress(isLoaded: isLoaded)
.onAppear { fakeNetworkCall() }
一切都好,但我不明白为什么。
想象一下“内联”视图修饰符,它会变得非常清晰。换句话说,将视图修改器的
content
中的 body
替换为它正在修改的实际视图:
if isLoaded {
ZStack {
Color.red
.ignoresSafeArea()
Text("Example")
.foregroundStyle(.white)
.font(.title)
.bold()
}
} else {
ZStack {
Color.blue
.ignoresSafeArea()
Text("Example")
.foregroundStyle(.white)
.font(.title)
.bold()
}
.onAppear { fakeNetworkCall() }
}
onAppear
修饰符修改ZStack
分支中的else
。由于 if
语句最初为 true,因此 else
中的视图永远不会出现,因此 onAppear
永远不会被调用。
如果将
progress
放在 onAppear
之前,onAppear
会修改整个 if...else
语句(又名 _ConditionalContent
),即视图修改器的主体。这个视图总是出现。
有点像这样
Group {
if isLoaded {
ZStack {
Color.red
.ignoresSafeArea()
Text("Example")
.foregroundStyle(.white)
.font(.title)
.bold()
}
} else {
ZStack {
Color.blue
.ignoresSafeArea()
Text("Example")
.foregroundStyle(.white)
.font(.title)
.bold()
}
}
}
.onAppear { fakeNetworkCall() }