问题描述
我想知道 SwiftUI 中的 onAppear 和 onDisappear(我写这篇文章时为 Xcode 11 beta 6)的行为是否对开发人员更有用,或者它只是一个问题而不是功能.
I would like to know if the behavior of onAppear and onDisappear in SwiftUI (Xcode 11 beta 6 when I wrote this) is what a developer would find more useful or it is just being more a problem than a feature.
现在,如果我们使用级联导航,如您将在我附加的示例代码中找到的(在 Xcode 11b6 中编译和运行良好),用户来回导航的控制台输出只会触发 onAppear 仅在向前加载新视图的情况(意味着更深).
Right now, if we use a cascaded navigation as you will find in the sample code I attach (that compiles and runs fine in Xcode 11b6), a console output of a user navigating back and forth would just trigger onAppear only in the case of a new view load in the forward direction (meaning going deeper).
在导航中:根 -> NestedView1 -> NestedView2 -> NestedView3 ,向每个视图阶段添加调试助手时,
In the navigation:Root -> NestedView1 -> NestedView2 -> NestedView3 ,when adding a debug helper to each view stage,
.onAppear(perform: {print("onAppear level N")})
.onDisappear(perform: {print("onDisappear level N")})
调试控制台会显示
onAppear 根级别 0
onAppear level 1
onAppear level 2
onAppear level 3
(无 onDisappear 触发)
(No onDisappear triggering)
但是要回去根 <- NestedView1 <- NestedView2 <- NestedView3
but travelling backRoot <- NestedView1 <- NestedView2 <- NestedView3
调试控制台会显示......什么都没有
debug console would show ... nothing
(无 onAppear 或 onDisappear 触发)
(No onAppear or onDisappear triggering)
struct NestedViewLevel3: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
Text("Level 3")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 3", displayMode: .inline)
.onAppear(perform: {print("onAppear level 3")})
.onDisappear(perform: {print("onDisappear level 3")})
}
}
struct NestedViewLevel2: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel3()) {
Text("To level 3")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
Text("Level 2")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 2", displayMode: .inline)
.onAppear(perform: {print("onAppear level 2")})
.onDisappear(perform: {print("onDisappear level 2")})
}
}
struct NestedViewLevel1: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
var body: some View {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel2()) {
Text("To level 2")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
Text("Level 1")
Spacer()
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Back")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.blue)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
}
Spacer()
}
.navigationBarBackButtonHidden(false)
.navigationBarTitle("Level 1", displayMode: .inline)
.onAppear(perform: {print("onAppear level 1")})
.onDisappear(perform: {print("onDisappear level 1")})
}
}
struct RootViewLevel0: View {
var body: some View {
NavigationView {
VStack {
Spacer()
NavigationLink(destination: NestedViewLevel1()) {
Text("To level 1")
.padding(.horizontal, 15)
.padding(.vertical, 2)
.foregroundColor(Color.white)
.clipped(antialiased: true)
.background(
RoundedRectangle(cornerRadius: 20)
.foregroundColor(Color.gray)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: 40, alignment: .center)
)
.shadow(radius: 10)
}
Spacer()
}
}
.navigationBarTitle("Root level 0", displayMode: .inline)
.navigationBarBackButtonHidden(false)
.navigationViewStyle(StackNavigationViewStyle())
.onAppear(perform: {print("onAppear root level 0")})
.onDisappear(perform: {print("onDisappear root level 0")})
}
}
struct ContentView: View {
var body: some View {
RootViewLevel0()
}
}
}
现在,开发人员是否宁愿拥有 onAppear 和 onDisappear:
Now, would a developer rather have onAppear and onDisappear:
1) 触发仅需要执行一次且仅在用户向前移动时执行的操作,例如当前观察到的行为.
1) Triggered for the purpose of launching actions that need to be performed only once and only when the user travels forward, like in the current observed behavior.
2) 每次视图出现时触发,更像是动作名称的意思,无论是向后、向前还是任意次数.
2) Triggered each time the view appears, more like the action name seems to mean, be it backwards, forwards and any number of times.
我会选择选项 2,简单粗暴(也是我目前需要的),但我在 NavigationView 方面还是个天真的新手,选项 2 可能会破坏很多我没有考虑的既定范例.
I'd take the option 2, simple and brutal (and what I currently need), but I am quite a naive newbie at NavigationView, and option 2 may break a lot of established paradigms I'm not taking into account.
您的反馈将帮助我确定相应的 SwiftUI 反馈助手案例是否有正当理由.
Your feedback will help me find out if the corresponding Feedback Assistant case for SwiftUI is on legitimate grounds.
推荐答案
这是 Apple 的一个错误.
It was a bug on Apple's end.
.onAppear()
现在可以在 iOS 13.1 和 Xcode 11 Beta 7 中正常工作.
.onAppear()
now works as it is supposed to in iOS 13.1 and Xcode 11 Beta 7.
当向前和向后导航到 NavigationView 时,.onAppear()
将触发.
When navigating forwards and backwards to the NavigationView, .onAppear()
will trigger.
这篇关于SwiftUI 应用程序的 NavigationView 中的 onAppear 和 onDisappear 是否按预期运行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!