【问题标题】:onDisappear not called when a modal View is dismissed关闭模式视图时未调用 onDisappear
【发布时间】:2020-02-29 17:58:47
【问题描述】:

我依靠 SwiftUI 的 .onDisappear 来执行一些逻辑,但是当用户使用滑动手势关闭模态呈现的视图时,它不会被调用。重现

  • 以“ChildView 1”模式呈现视图
  • 在此视图中,将“ChildView 2”推送为子导航
  • 向下滑动可关闭模式视图。

“ChildView 2”的 .onDisappear 没有被调用。

要重现的示例代码

import SwiftUI

struct ContentView: View {
    @State var isShowingModal
    var body: some View {
        NavigationView {
            Button(action: {
                self.isShowingModal.toggle()
            }) {
                Text("Show Modal")
            }
        }
        .sheet(isPresented: $isShowingModal) {
            NavigationView {
                ChildView(title: 1)
            }
        }
    }
}

struct ChildView: View {
    let title: Int
    var body: some View {

        NavigationLink(destination: ChildView(title: title + 1)) {
            Text("Show Child")
        }
        .navigationBarTitle("View \(title)")


        .onAppear {
            print("onAppear ChildView \(self.title)")
        }
        .onDisappear {
            print("onDisappear ChildView \(self.title)")
        }
    }
}

输出是:

onAppear ChildView 1
onAppear ChildView 2
onDisappear ChildView 1

【问题讨论】:

  • .onAppear 在视图被添加到视图层次结构时被调用,.onDisappear 在被移除时被调用。在您的用例中,ChildView 2 不会从超级视图中删除 - 已删除窗口。一般来说,以防万一,将逻辑移到那里不是可靠的方法。
  • @Asperi 我认为这是解释原因的最相关的答案。

标签: ios swiftui


【解决方案1】:

如果您正在寻找在实际模态被解除时发生的逻辑,您会想在这里调用它,我打印出 Modal Dismissed:

struct ContentView: View {
    @State var isShowingModal = false
    var body: some View {
        NavigationView {
            Button(action: {
                self.isShowingModal.toggle()
            }) {
                Text("Show Modal")
            }
        }
        .sheet(isPresented: $isShowingModal) {
            NavigationView {
                ChildView(title: 1)
            }
            .onDisappear {
                print("Modal Dismissed")
            }
        }
    }
}

【讨论】:

  • 但我不想在ContentView 中混合ChildView 的任何逻辑。在我的ChildView 中,当.onAppear 被调用时,我正在建立网络连接,并希望在视图消失时关闭它。
  • 我没有使用NavigationView 在我的子视图中,而是在它之外。在模态呈现时,我只创建了一个导航堆栈。所有的 ChildView 都被推送到同一个堆栈中。
  • @Jan 对不起,我的错误......忽略!
【解决方案2】:
struct ContentView: View {
    @State var isShowingModal = false
    var body: some View {
        NavigationView {
            Button(action: {
                self.isShowingModal.toggle()
            }) {
                Text("Show Modal")
            }
        }
        .sheet(isPresented: $isShowingModal) {
            NavigationView {
                ChildView(title: 1)
            }
        }
    }
}

在此代码中,您有 NavigationView,并且在呈现工作表时,您将另一个 NavigationView 推到那里。这就是麻烦的根源

您不需要任何 NavigationView 来呈现模式。如果你想从 modal 中展示另一个 modal,你可以使用

import SwiftUI

struct ContentView: View {
    var body: some View {
         ChildView(title: 1)
    }
}

struct ChildView: View {
    @State var isShowingModal = false
    let title: Int
    var body: some View {

        Button(action: {
                self.isShowingModal.toggle()
            }) {
                Text("Show Modal \(title)").font(.largeTitle)
            }
        .sheet(isPresented: $isShowingModal) {
            ChildView(title: self.title + 1)

        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

更新

来自苹果 人机界面指南

模态是一种设计技术,它以一种临时模式呈现内容,该模式与用户之前的当前上下文不同,需要明确的操作才能退出

【讨论】:

  • 我的问题是关于以模态方式呈现导航然后在该导航上推送视图的情况
  • @Jan 在这种情况下,如果用户关闭工作表(模态视图),它将关闭它而不将其从导航堆栈中弹出。如果您喜欢这种行为,请使用它:-) 我还建议您使用工具来检查内存是如何分配和释放的。
  • @Jan see swiftui-lab.com/modal-dismiss-gesture 最终可以帮助您通过向下滑动禁用关闭,或者在没有标准后退按钮的情况下从导航堆栈中弹出。
猜你喜欢
  • 1970-01-01
  • 2015-09-29
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-03
  • 2021-06-07
相关资源
最近更新 更多