SwiftUI应用程序的NavigationView中的onAppear和onDisappear是否表现正常?

时间:2019-08-26 16:54:17

标签: swift swiftui ios-navigationview

我想知道在SwiftUI(我编写本文时为Xcode 11 beta 6)中onAppear和Disappear的行为是开发人员会发现更有用的东西,还是仅仅是一个问题而不是功能。

>

现在,如果我们使用级联导航(如您在我附加的示例代码中所找到的那样(在Xcode 11b6中编译并运行良好)),则来回导航的用户的控制台输出只会在onAppear中触发新视图正向加载的情况(意味着更深)。

在导航中: 根-> NestedView1-> NestedView2-> NestedView3, 在每个视图阶段添加调试助手时,

  .onAppear(perform: {print("onAppear level N")})
  .onDisappear(perform: {print("onDisappear level N")})

调试控制台会显示

onAppear root level 0
onAppear level 1
onAppear level 2
onAppear level 3

(没有onDisappear触发)

但回去 根<-NestedView1 <-NestedView2 <-NestedView3

调试控制台将不显示任何内容

(没有onAppear或onDisappear触发)

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:

1)被触发以启动仅需一次且仅当用户向前行驶时才执行的动作,例如当前观察到的行为。

2)每次视图出现时都会触发,更像是动作名称的意思,即后退,前进和任意次数。

我会选择选项2,简单而残酷(以及我目前所需要的),但是我是NavigationView的一个天真的新手,选项2可能打破了许多我没有考虑的既定范例。

您的反馈将帮助我了解SwiftUI的相应“反馈助手”案例是否有正当理由。

3 个答案:

答案 0 :(得分:4)

从XCode 11.2 beta版(2019年2月10日发布)开始,两种方法(包括.onDisappear())都已正确触发。

请注意,.onDisappear()直到此beta版本才被触发。

答案 1 :(得分:2)

这是苹果公司的错误。

.onAppear()现在可以在iOS 13.1和XCode 11 Beta 7中正常工作。

向前和向后导航到NavigationView时,.onAppear()将触发。

答案 2 :(得分:0)

两个命令: .onDisappear(perform:)&.onAppear(perform:)

正在调试NavigationView(.navigationBarTitle)功能:

    .navigationBarTitle("Opciones", displayMode: .inline)

使用时,navigationBarTitle会被删除或无法在您使用的视图中调用它。这是同时发生的: .onDisappear(perform:) .onAppear(perform:)

使用Xcode版本12.2(12B45b)