Ios 当模式视图被取消时,不会调用onDisappear

Ios 当模式视图被取消时,不会调用onDisappear,ios,swiftui,Ios,Swiftui,我依靠SwiftUI的.onDisappear来执行一些逻辑,但当用户用滑动手势取消一个以模式显示的视图时,不会调用它。复制 以“ChildView 1”的形式呈现视图 在此视图上,将“ChildView 2”作为导航子视图推送 向下滑动以关闭模式视图 未调用“ChildView 2”的.onDisappear 要复制的示例代码 import SwiftUI struct ContentView: View { @State var isShowingModal var b

我依靠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

如果您希望在实际模态被解除时出现逻辑,您需要在这里调用它,在这里我打印出模态解除:

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")
            }
        }
    }
}
在这段代码中,您有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()
    }
}

更新

来自苹果 人机界面指南


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

,但我不想在
内容视图
中混用
子视图
的任何逻辑。在我的
ChildView
中,当调用
.onAppear
时,我正在建立网络连接,并希望在视图消失时将其关闭。我不是在我的子视图中使用
导航视图,而是在它之外使用。在以模态方式呈现时,我只创建了一个导航堆栈。所有的ChildView都被推到同一个堆栈上。@Jan抱歉,我的错误。。。漠视将视图添加到视图层次结构时调用
.onAppear
,删除时调用
.onDisappear
。在您的用例中,
ChildView 2
不会从superview-removed窗口中删除。一般来说,为了以防万一,将逻辑移到这里是不可靠的。@Asperi我认为这是解释原因的最相关的答案。我的问题是关于以模式显示导航,然后在此基础上推送视图的情况navigation@Jan在这种情况下,如果用户关闭图纸(模式视图)它会在不将其从导航堆栈中弹出的情况下将其关闭。如果您喜欢这种行为,请使用:-)我还建议您使用工具来检查内存是如何分配和释放的。@Jan请查看哪种方法最终可以帮助您通过向下滑动来禁用Dismission,或者在没有标准后退按钮的情况下从导航堆栈中弹出。
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()
    }
}