关闭模式视图时未调用 onDisappear

Posted

技术标签:

【中文标题】关闭模式视图时未调用 onDisappear【英文标题】:onDisappear not called when a modal View is dismissed 【发布时间】: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 我认为这是解释原因的最相关的答案。 【参考方案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 最终可以帮助您通过向下滑动禁用关闭,或者在没有标准后退按钮的情况下从导航堆栈中弹出。

以上是关于关闭模式视图时未调用 onDisappear的主要内容,如果未能解决你的问题,请参考以下文章

关闭屏幕时未调用 UICollectionView performBatchUpdates 完成

关闭时未调用 Alamofire 请求

显示关闭时未调用 didRangeBeacons 方法

实现可折叠表视图时未调用 UITableView didSelectRowAtIndexPath

单击提交时未调用Django视图功能

调用 Selector 方法时未从 Superview 中删除视图